vulkan: Remove GskVulkanRenderer

We want to introduce a new one next.

Technically, this breaks API, because gsk_vulkan_renderer_new() is going
away, but practically, we're gonna bring it back once we introduce that
renderer in a few commits.
This commit is contained in:
Benjamin Otte 2023-08-12 23:07:51 +02:00
parent 40854f2ae9
commit 1e54e838e0
106 changed files with 2 additions and 10974 deletions

View File

@ -28,9 +28,6 @@
#ifdef GDK_WINDOWING_BROADWAY
#include "gsk/broadway/gskbroadwayrenderer.h"
#endif
#ifdef GDK_RENDERING_VULKAN
#include "gsk/vulkan/gskvulkanrenderer.h"
#endif
#include <cairo.h>
#ifdef CAIRO_HAS_SVG_SURFACE
@ -1157,11 +1154,6 @@ node_editor_window_realize (GtkWidget *widget)
node_editor_window_add_renderer (self,
gsk_gl_renderer_new (),
"OpenGL");
#ifdef GDK_RENDERING_VULKAN
node_editor_window_add_renderer (self,
gsk_vulkan_renderer_new (),
"Vulkan");
#endif
#ifdef GDK_WINDOWING_BROADWAY
node_editor_window_add_renderer (self,
gsk_broadway_renderer_new (),

View File

@ -58,9 +58,6 @@
#ifdef GDK_WINDOWING_BROADWAY
#include "broadway/gskbroadwayrenderer.h"
#endif
#ifdef GDK_RENDERING_VULKAN
#include "vulkan/gskvulkanrenderer.h"
#endif
#ifdef GDK_WINDOWING_MACOS
#include <gdk/macos/gdkmacos.h>
#endif
@ -507,10 +504,6 @@ get_renderer_for_name (const char *renderer_name)
else if (g_ascii_strcasecmp (renderer_name, "opengl") == 0 ||
g_ascii_strcasecmp (renderer_name, "gl") == 0)
return GSK_TYPE_GL_RENDERER;
#ifdef GDK_RENDERING_VULKAN
else if (g_ascii_strcasecmp (renderer_name, "vulkan") == 0)
return GSK_TYPE_VULKAN_RENDERER;
#endif
else if (g_ascii_strcasecmp (renderer_name, "help") == 0)
{
g_print ("Supported arguments for GSK_RENDERER environment variable:\n");
@ -522,11 +515,6 @@ get_renderer_for_name (const char *renderer_name)
g_print (" cairo - Use the Cairo fallback renderer\n");
g_print (" opengl - Use the OpenGL renderer\n");
g_print (" gl - Use the OpenGL renderer\n");
#ifdef GDK_RENDERING_VULKAN
g_print (" vulkan - Use the Vulkan renderer\n");
#else
g_print (" vulkan - Disabled during GTK build\n");
#endif
g_print (" help - Print this help\n\n");
g_print ("Other arguments will cause a warning and be ignored.\n");
}

View File

@ -104,56 +104,11 @@ if get_variable('broadway_enabled')
gsk_public_headers += gsk_public_broadway_headers
endif
if have_vulkan
gsk_public_vulkan_headers = files([
'vulkan/gskvulkanrenderer.h'
])
install_headers(gsk_public_vulkan_headers, subdir: 'gtk-4.0/gsk/vulkan')
gsk_public_headers += gsk_public_vulkan_headers
endif
gsk_private_vulkan_shaders = []
gsk_private_vulkan_compiled_shaders = []
gsk_private_vulkan_compiled_shaders_deps = []
gsk_private_vulkan_shader_headers = []
if have_vulkan
gsk_private_sources += files([
'vulkan/gskvulkanblendmodeop.c',
'vulkan/gskvulkanblurop.c',
'vulkan/gskvulkanborderop.c',
'vulkan/gskvulkanbuffer.c',
'vulkan/gskvulkanclearop.c',
'vulkan/gskvulkanclip.c',
'vulkan/gskvulkancolormatrixop.c',
'vulkan/gskvulkancolorop.c',
'vulkan/gskvulkancommandpool.c',
'vulkan/gskvulkanconvertop.c',
'vulkan/gskvulkancrossfadeop.c',
'vulkan/gskvulkandownloadop.c',
'vulkan/gskvulkanglyphcache.c',
'vulkan/gskvulkanglyphop.c',
'vulkan/gskvulkanimage.c',
'vulkan/gskvulkaninsetshadowop.c',
'vulkan/gskvulkanlineargradientop.c',
'vulkan/gskvulkanmaskop.c',
'vulkan/gskvulkanmemory.c',
'vulkan/gskvulkanop.c',
'vulkan/gskvulkanoutsetshadowop.c',
'vulkan/gskvulkanpushconstantsop.c',
'vulkan/gskvulkanrender.c',
'vulkan/gskvulkanrenderer.c',
'vulkan/gskvulkanrenderpass.c',
'vulkan/gskvulkanrenderpassop.c',
'vulkan/gskvulkanscissorop.c',
'vulkan/gskvulkanshaderop.c',
'vulkan/gskvulkantextureop.c',
'vulkan/gskvulkanuploadop.c',
])
subdir('vulkan/resources')
endif # have_vulkan
if get_variable('broadway_enabled')
gsk_public_sources += files([
'broadway/gskbroadwayrenderer.c',

View File

@ -1,119 +0,0 @@
#include "config.h"
#include "gskvulkanblendmodeopprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanshaderopprivate.h"
#include "vulkan/resources/blend-mode.vert.h"
typedef struct _GskVulkanBlendModeOp GskVulkanBlendModeOp;
struct _GskVulkanBlendModeOp
{
GskVulkanShaderOp op;
graphene_rect_t bounds;
GskBlendMode blend_mode;
struct {
graphene_rect_t rect;
graphene_rect_t tex_rect;
guint32 image_descriptor;
} top, bottom;
};
static void
gsk_vulkan_blend_mode_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanBlendModeOp *self = (GskVulkanBlendModeOp *) op;
print_indent (string, indent);
print_rect (string, &self->bounds);
g_string_append_printf (string, "blend-mode %d%% ", self->blend_mode);
print_newline (string);
}
static void
gsk_vulkan_blend_mode_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
GskVulkanBlendModeOp *self = (GskVulkanBlendModeOp *) op;
GskVulkanBlendModeInstance *instance = (GskVulkanBlendModeInstance *) (data + ((GskVulkanShaderOp *) op)->vertex_offset);
gsk_rect_to_float (&self->bounds, instance->rect);
gsk_rect_to_float (&self->top.rect, instance->top_rect);
gsk_rect_to_float (&self->bottom.rect, instance->bottom_rect);
gsk_rect_to_float (&self->top.tex_rect, instance->top_tex_rect);
gsk_rect_to_float (&self->bottom.tex_rect, instance->bottom_tex_rect);
instance->top_tex_id = self->top.image_descriptor;
instance->bottom_tex_id = self->bottom.image_descriptor;
instance->blend_mode = self->blend_mode;
}
static void
gsk_vulkan_blend_mode_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
GskVulkanBlendModeOp *self = (GskVulkanBlendModeOp *) op;
GskVulkanShaderOp *shader = (GskVulkanShaderOp *) op;
self->top.image_descriptor = gsk_vulkan_render_get_image_descriptor (render,
shader->images[0],
GSK_VULKAN_SAMPLER_DEFAULT);
self->bottom.image_descriptor = gsk_vulkan_render_get_image_descriptor (render,
shader->images[1],
GSK_VULKAN_SAMPLER_DEFAULT);
}
static const GskVulkanShaderOpClass GSK_VULKAN_BLEND_MODE_OP_CLASS = {
{
GSK_VULKAN_OP_SIZE (GskVulkanBlendModeOp),
GSK_VULKAN_STAGE_SHADER,
gsk_vulkan_shader_op_finish,
gsk_vulkan_blend_mode_op_print,
gsk_vulkan_shader_op_count_vertex_data,
gsk_vulkan_blend_mode_op_collect_vertex_data,
gsk_vulkan_blend_mode_op_reserve_descriptor_sets,
gsk_vulkan_shader_op_command
},
"blend-mode",
2,
&gsk_vulkan_blend_mode_info,
};
void
gsk_vulkan_blend_mode_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const graphene_rect_t *bounds,
const graphene_point_t *offset,
GskBlendMode blend_mode,
GskVulkanImage *top_image,
const graphene_rect_t *top_rect,
const graphene_rect_t *top_tex_rect,
GskVulkanImage *bottom_image,
const graphene_rect_t *bottom_rect,
const graphene_rect_t *bottom_tex_rect)
{
GskVulkanBlendModeOp *self;
self = (GskVulkanBlendModeOp *) gsk_vulkan_shader_op_alloc (render,
&GSK_VULKAN_BLEND_MODE_OP_CLASS,
clip,
(GskVulkanImage *[2]) {
top_image,
bottom_image
});
graphene_rect_offset_r (bounds, offset->x, offset->y, &self->bounds);
self->blend_mode = blend_mode;
graphene_rect_offset_r (top_rect, offset->x, offset->y, &self->top.rect);
gsk_vulkan_normalize_tex_coords (&self->top.tex_rect, bounds, top_tex_rect);
graphene_rect_offset_r (bottom_rect, offset->x, offset->y, &self->bottom.rect);
gsk_vulkan_normalize_tex_coords (&self->bottom.tex_rect, bounds, bottom_tex_rect);
}

View File

@ -1,21 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_blend_mode_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const graphene_rect_t *bounds,
const graphene_point_t *offset,
GskBlendMode blend_mode,
GskVulkanImage *top_image,
const graphene_rect_t *top_rect,
const graphene_rect_t *top_tex_rect,
GskVulkanImage *bottom_image,
const graphene_rect_t *bottom_rect,
const graphene_rect_t *bottom_tex_rect);
G_END_DECLS

View File

@ -1,97 +0,0 @@
#include "config.h"
#include "gskvulkanbluropprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanshaderopprivate.h"
#include "vulkan/resources/blur.vert.h"
typedef struct _GskVulkanBlurOp GskVulkanBlurOp;
struct _GskVulkanBlurOp
{
GskVulkanShaderOp op;
graphene_rect_t rect;
graphene_rect_t tex_rect;
float radius;
guint32 image_descriptor;
};
static void
gsk_vulkan_blur_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanBlurOp *self = (GskVulkanBlurOp *) op;
print_indent (string, indent);
print_rect (string, &self->rect);
g_string_append_printf (string, "blur %g",
self->radius);
print_newline (string);
}
static void
gsk_vulkan_blur_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
GskVulkanBlurOp *self = (GskVulkanBlurOp *) op;
GskVulkanBlurInstance *instance = (GskVulkanBlurInstance *) (data + ((GskVulkanShaderOp *) op)->vertex_offset);
gsk_rect_to_float (&self->rect, instance->rect);
gsk_rect_to_float (&self->tex_rect, instance->tex_rect);
instance->tex_id = self->image_descriptor;
instance->radius = self->radius;
}
static void
gsk_vulkan_blur_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
GskVulkanBlurOp *self = (GskVulkanBlurOp *) op;
GskVulkanShaderOp *shader = (GskVulkanShaderOp *) op;
self->image_descriptor = gsk_vulkan_render_get_image_descriptor (render,
shader->images[0],
GSK_VULKAN_SAMPLER_DEFAULT);
}
static const GskVulkanShaderOpClass GSK_VULKAN_BLUR_OP_CLASS = {
{
GSK_VULKAN_OP_SIZE (GskVulkanBlurOp),
GSK_VULKAN_STAGE_SHADER,
gsk_vulkan_shader_op_finish,
gsk_vulkan_blur_op_print,
gsk_vulkan_shader_op_count_vertex_data,
gsk_vulkan_blur_op_collect_vertex_data,
gsk_vulkan_blur_op_reserve_descriptor_sets,
gsk_vulkan_shader_op_command
},
"blur",
1,
&gsk_vulkan_blur_info,
};
void
gsk_vulkan_blur_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
GskVulkanImage *image,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
float radius)
{
GskVulkanBlurOp *self;
g_assert (radius > 0);
self = (GskVulkanBlurOp *) gsk_vulkan_shader_op_alloc (render, &GSK_VULKAN_BLUR_OP_CLASS, clip, &image);
graphene_rect_offset_r (rect, offset->x, offset->y, &self->rect);
gsk_vulkan_normalize_tex_coords (&self->tex_rect, rect, tex_rect);
self->radius = radius;
}

View File

@ -1,16 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_blur_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
GskVulkanImage *image,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
float radius);
G_END_DECLS

View File

@ -1,123 +0,0 @@
#include "config.h"
#include "gskvulkanborderopprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanshaderopprivate.h"
#include "gsk/gskroundedrectprivate.h"
#include "vulkan/resources/border.vert.h"
typedef struct _GskVulkanBorderOp GskVulkanBorderOp;
struct _GskVulkanBorderOp
{
GskVulkanShaderOp op;
GskRoundedRect outline;
float widths[4];
GdkRGBA colors[4];
};
static void
gsk_vulkan_border_op_finish (GskVulkanOp *op)
{
}
static void
gsk_vulkan_border_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanBorderOp *self = (GskVulkanBorderOp *) op;
print_indent (string, indent);
print_rounded_rect (string, &self->outline);
g_string_append (string, "border ");
print_rgba (string, &self->colors[0]);
if (!gdk_rgba_equal (&self->colors[3], &self->colors[0]) ||
!gdk_rgba_equal (&self->colors[2], &self->colors[0]) ||
!gdk_rgba_equal (&self->colors[1], &self->colors[0]))
{
print_rgba (string, &self->colors[1]);
print_rgba (string, &self->colors[2]);
print_rgba (string, &self->colors[3]);
}
g_string_append_printf (string, "%g ", self->widths[0]);
if (self->widths[0] != self->widths[1] ||
self->widths[0] != self->widths[2] ||
self->widths[0] != self->widths[3])
g_string_append_printf (string, "%g %g %g ", self->widths[1], self->widths[2], self->widths[3]);
print_newline (string);
}
static void
gsk_vulkan_border_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
GskVulkanBorderOp *self = (GskVulkanBorderOp *) op;
GskVulkanBorderInstance *instance = (GskVulkanBorderInstance *) (data + ((GskVulkanShaderOp *) op)->vertex_offset);
guint i;
gsk_rounded_rect_to_float (&self->outline, graphene_point_zero (), instance->rect);
for (i = 0; i < 4; i++)
{
instance->border_widths[i] = self->widths[i];
gsk_vulkan_rgba_to_float (&self->colors[i], (gpointer) &instance->border_colors[4 * i]);
}
}
static void
gsk_vulkan_border_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
}
static GskVulkanOp *
gsk_vulkan_border_op_command (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer)
{
return gsk_vulkan_shader_op_command_n (op, render, render_pass, command_buffer, 8);
}
static const GskVulkanShaderOpClass GSK_VULKAN_BORDER_OP_CLASS = {
{
GSK_VULKAN_OP_SIZE (GskVulkanBorderOp),
GSK_VULKAN_STAGE_SHADER,
gsk_vulkan_border_op_finish,
gsk_vulkan_border_op_print,
gsk_vulkan_shader_op_count_vertex_data,
gsk_vulkan_border_op_collect_vertex_data,
gsk_vulkan_border_op_reserve_descriptor_sets,
gsk_vulkan_border_op_command
},
"border",
0,
&gsk_vulkan_border_info,
};
void
gsk_vulkan_border_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const GskRoundedRect *outline,
const graphene_point_t *offset,
const float widths[4],
const GdkRGBA colors[4])
{
GskVulkanBorderOp *self;
guint i;
self = (GskVulkanBorderOp *) gsk_vulkan_shader_op_alloc (render, &GSK_VULKAN_BORDER_OP_CLASS, clip, NULL);
self->outline = *outline;
gsk_rounded_rect_offset (&self->outline, offset->x, offset->y);
for (i = 0; i < 4; i++)
{
self->widths[i] = widths[i];
self->colors[i] = colors[i];
}
}

View File

@ -1,16 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_border_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const GskRoundedRect *outline,
const graphene_point_t *offset,
const float widths[4],
const GdkRGBA colors[4]);
G_END_DECLS

View File

@ -1,122 +0,0 @@
#include "config.h"
#include "gskvulkanbufferprivate.h"
#include "gskvulkanmemoryprivate.h"
#include "gskvulkanprivate.h"
struct _GskVulkanBuffer
{
GdkVulkanContext *vulkan;
gsize size;
VkBuffer vk_buffer;
GskVulkanMemory *memory;
};
static GskVulkanBuffer *
gsk_vulkan_buffer_new_internal (GdkVulkanContext *context,
gsize size,
VkBufferUsageFlags usage)
{
VkMemoryRequirements requirements;
GskVulkanBuffer *self;
self = g_new0 (GskVulkanBuffer, 1);
self->vulkan = g_object_ref (context);
self->size = size;
GSK_VK_CHECK (vkCreateBuffer, gdk_vulkan_context_get_device (context),
&(VkBufferCreateInfo) {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = size,
.flags = 0,
.usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE
},
NULL,
&self->vk_buffer);
vkGetBufferMemoryRequirements (gdk_vulkan_context_get_device (context),
self->vk_buffer,
&requirements);
self->memory = gsk_vulkan_memory_new (context,
requirements.memoryTypeBits,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
requirements.size);
GSK_VK_CHECK (vkBindBufferMemory, gdk_vulkan_context_get_device (context),
self->vk_buffer,
gsk_vulkan_memory_get_device_memory (self->memory),
0);
return self;
}
GskVulkanBuffer *
gsk_vulkan_buffer_new (GdkVulkanContext *context,
gsize size)
{
return gsk_vulkan_buffer_new_internal (context, size,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
}
GskVulkanBuffer *
gsk_vulkan_buffer_new_storage (GdkVulkanContext *context,
gsize size)
{
return gsk_vulkan_buffer_new_internal (context, size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
}
GskVulkanBuffer *
gsk_vulkan_buffer_new_map (GdkVulkanContext *context,
gsize size,
GskVulkanMapMode mode)
{
return gsk_vulkan_buffer_new_internal (context,
size,
(mode & GSK_VULKAN_READ ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : 0) |
(mode & GSK_VULKAN_WRITE ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : 0));
}
void
gsk_vulkan_buffer_free (GskVulkanBuffer *self)
{
vkDestroyBuffer (gdk_vulkan_context_get_device (self->vulkan),
self->vk_buffer,
NULL);
gsk_vulkan_memory_free (self->memory);
g_object_unref (self->vulkan);
g_free (self);
}
VkBuffer
gsk_vulkan_buffer_get_buffer (GskVulkanBuffer *self)
{
return self->vk_buffer;
}
gsize
gsk_vulkan_buffer_get_size (GskVulkanBuffer *self)
{
return self->size;
}
guchar *
gsk_vulkan_buffer_map (GskVulkanBuffer *self)
{
return gsk_vulkan_memory_map (self->memory);
}
void
gsk_vulkan_buffer_unmap (GskVulkanBuffer *self)
{
gsk_vulkan_memory_unmap (self->memory);
}

View File

@ -1,32 +0,0 @@
#pragma once
#include <gdk/gdk.h>
G_BEGIN_DECLS
typedef struct _GskVulkanBuffer GskVulkanBuffer;
typedef enum
{
GSK_VULKAN_READ = (1 << 0),
GSK_VULKAN_WRITE = (1 << 1),
GSK_VULKAN_READWRITE = GSK_VULKAN_READ | GSK_VULKAN_WRITE
} GskVulkanMapMode;
GskVulkanBuffer * gsk_vulkan_buffer_new (GdkVulkanContext *context,
gsize size);
GskVulkanBuffer * gsk_vulkan_buffer_new_storage (GdkVulkanContext *context,
gsize size);
GskVulkanBuffer * gsk_vulkan_buffer_new_map (GdkVulkanContext *context,
gsize size,
GskVulkanMapMode mode);
void gsk_vulkan_buffer_free (GskVulkanBuffer *buffer);
VkBuffer gsk_vulkan_buffer_get_buffer (GskVulkanBuffer *self);
gsize gsk_vulkan_buffer_get_size (GskVulkanBuffer *self);
guchar * gsk_vulkan_buffer_map (GskVulkanBuffer *self);
void gsk_vulkan_buffer_unmap (GskVulkanBuffer *self);
G_END_DECLS

View File

@ -1,115 +0,0 @@
#include "config.h"
#include "gskvulkanclearopprivate.h"
#include "gskvulkanprivate.h"
typedef struct _GskVulkanClearOp GskVulkanClearOp;
struct _GskVulkanClearOp
{
GskVulkanOp op;
cairo_rectangle_int_t rect;
GdkRGBA color;
};
static void
gsk_vulkan_clear_op_finish (GskVulkanOp *op)
{
}
static void
gsk_vulkan_clear_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanClearOp *self = (GskVulkanClearOp *) op;
print_indent (string, indent);
print_int_rect (string, &self->rect);
g_string_append_printf (string, "clear ");
print_rgba (string, &self->color);
print_newline (string);
}
static gsize
gsk_vulkan_clear_op_count_vertex_data (GskVulkanOp *op,
gsize n_bytes)
{
return n_bytes;
}
static void
gsk_vulkan_clear_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
}
static void
gsk_vulkan_clear_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
}
static void
gsk_vulkan_init_clear_value (VkClearValue *value,
const GdkRGBA *rgba)
{
gsk_vulkan_rgba_to_float (rgba, value->color.float32);
}
static GskVulkanOp *
gsk_vulkan_clear_op_command (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer)
{
GskVulkanClearOp *self = (GskVulkanClearOp *) op;
VkClearValue clear_value;
gsk_vulkan_init_clear_value (&clear_value, &self->color);
vkCmdClearAttachments (command_buffer,
1,
&(VkClearAttachment) {
VK_IMAGE_ASPECT_COLOR_BIT,
0,
clear_value,
},
1,
&(VkClearRect) {
{
{ self->rect.x, self->rect.y },
{ self->rect.width, self->rect.height },
},
0,
1
});
return op->next;
}
static const GskVulkanOpClass GSK_VULKAN_SCISSOR_OP_CLASS = {
GSK_VULKAN_OP_SIZE (GskVulkanClearOp),
GSK_VULKAN_STAGE_COMMAND,
gsk_vulkan_clear_op_finish,
gsk_vulkan_clear_op_print,
gsk_vulkan_clear_op_count_vertex_data,
gsk_vulkan_clear_op_collect_vertex_data,
gsk_vulkan_clear_op_reserve_descriptor_sets,
gsk_vulkan_clear_op_command
};
void
gsk_vulkan_clear_op (GskVulkanRender *render,
const cairo_rectangle_int_t *rect,
const GdkRGBA *color)
{
GskVulkanClearOp *self;
self = (GskVulkanClearOp *) gsk_vulkan_op_alloc (render, &GSK_VULKAN_SCISSOR_OP_CLASS);
self->rect = *rect;
self->color = *color;
}

View File

@ -1,13 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_clear_op (GskVulkanRender *render,
const cairo_rectangle_int_t *rect,
const GdkRGBA *color);
G_END_DECLS

View File

@ -1,301 +0,0 @@
#include "config.h"
#include "gskvulkanclipprivate.h"
#include "gskrectprivate.h"
#include "gskroundedrectprivate.h"
#include "gsktransform.h"
void
gsk_vulkan_clip_init_empty (GskVulkanClip *clip,
const graphene_rect_t *rect)
{
clip->type = GSK_VULKAN_CLIP_NONE;
gsk_rounded_rect_init_from_rect (&clip->rect, rect, 0);
}
void
gsk_vulkan_clip_init_rect (GskVulkanClip *clip,
const graphene_rect_t *rect)
{
clip->type = GSK_VULKAN_CLIP_RECT;
gsk_rounded_rect_init_from_rect (&clip->rect, rect, 0);
}
void
gsk_vulkan_clip_init_copy (GskVulkanClip *self,
const GskVulkanClip *src)
{
self->type = src->type;
gsk_rounded_rect_init_copy (&self->rect, &src->rect);
}
static gboolean
gsk_vulkan_clip_init_after_intersection (GskVulkanClip *self,
GskRoundedRectIntersection res)
{
if (res == GSK_INTERSECTION_NOT_REPRESENTABLE)
return FALSE;
if (res == GSK_INTERSECTION_EMPTY)
self->type = GSK_VULKAN_CLIP_ALL_CLIPPED;
else if (gsk_rounded_rect_is_rectilinear (&self->rect))
self->type = GSK_VULKAN_CLIP_RECT;
else
self->type = GSK_VULKAN_CLIP_ROUNDED;
return TRUE;
}
gboolean
gsk_vulkan_clip_intersect_rect (GskVulkanClip *dest,
const GskVulkanClip *src,
const graphene_rect_t *rect)
{
GskRoundedRectIntersection res;
if (graphene_rect_contains_rect (rect, &src->rect.bounds))
{
gsk_vulkan_clip_init_copy (dest, src);
return TRUE;
}
if (!gsk_rect_intersects (rect, &src->rect.bounds))
{
dest->type = GSK_VULKAN_CLIP_ALL_CLIPPED;
return TRUE;
}
switch (src->type)
{
case GSK_VULKAN_CLIP_ALL_CLIPPED:
dest->type = GSK_VULKAN_CLIP_ALL_CLIPPED;
break;
case GSK_VULKAN_CLIP_NONE:
gsk_vulkan_clip_init_copy (dest, src);
if (graphene_rect_intersection (&dest->rect.bounds, rect, &dest->rect.bounds))
dest->type = GSK_VULKAN_CLIP_RECT;
else
dest->type = GSK_VULKAN_CLIP_ALL_CLIPPED;
break;
case GSK_VULKAN_CLIP_RECT:
gsk_vulkan_clip_init_copy (dest, src);
if (!graphene_rect_intersection (&dest->rect.bounds, rect, &dest->rect.bounds))
dest->type = GSK_VULKAN_CLIP_ALL_CLIPPED;
break;
case GSK_VULKAN_CLIP_ROUNDED:
res = gsk_rounded_rect_intersect_with_rect (&src->rect, rect, &dest->rect);
if (!gsk_vulkan_clip_init_after_intersection (dest, res))
return FALSE;
break;
default:
g_assert_not_reached ();
return FALSE;
}
return TRUE;
}
gboolean
gsk_vulkan_clip_intersect_rounded_rect (GskVulkanClip *dest,
const GskVulkanClip *src,
const GskRoundedRect *rounded)
{
GskRoundedRectIntersection res;
if (gsk_rounded_rect_contains_rect (rounded, &src->rect.bounds))
{
gsk_vulkan_clip_init_copy (dest, src);
return TRUE;
}
if (!gsk_rect_intersects (&rounded->bounds, &src->rect.bounds))
{
dest->type = GSK_VULKAN_CLIP_ALL_CLIPPED;
return TRUE;
}
switch (src->type)
{
case GSK_VULKAN_CLIP_ALL_CLIPPED:
dest->type = GSK_VULKAN_CLIP_ALL_CLIPPED;
break;
case GSK_VULKAN_CLIP_NONE:
dest->type = GSK_VULKAN_CLIP_ROUNDED;
gsk_rounded_rect_init_copy (&dest->rect, rounded);
break;
case GSK_VULKAN_CLIP_RECT:
res = gsk_rounded_rect_intersect_with_rect (rounded, &src->rect.bounds, &dest->rect);
if (!gsk_vulkan_clip_init_after_intersection (dest, res))
return FALSE;
break;
case GSK_VULKAN_CLIP_ROUNDED:
res = gsk_rounded_rect_intersection (&src->rect, rounded, &dest->rect);
if (!gsk_vulkan_clip_init_after_intersection (dest, res))
return FALSE;
break;
default:
g_assert_not_reached ();
return FALSE;
}
return TRUE;
}
void
gsk_vulkan_clip_scale (GskVulkanClip *dest,
const GskVulkanClip *src,
float scale_x,
float scale_y)
{
dest->type = src->type;
gsk_rounded_rect_scale_affine (&dest->rect,
&src->rect,
1.0f / scale_x, 1.0f / scale_y,
0, 0);
}
gboolean
gsk_vulkan_clip_transform (GskVulkanClip *dest,
const GskVulkanClip *src,
GskTransform *transform,
const graphene_rect_t *viewport)
{
switch (src->type)
{
default:
g_assert_not_reached();
return FALSE;
case GSK_VULKAN_CLIP_ALL_CLIPPED:
gsk_vulkan_clip_init_copy (dest, src);
return TRUE;
case GSK_VULKAN_CLIP_NONE:
gsk_vulkan_clip_init_empty (dest, viewport);
return TRUE;
case GSK_VULKAN_CLIP_RECT:
case GSK_VULKAN_CLIP_ROUNDED:
switch (gsk_transform_get_category (transform))
{
case GSK_TRANSFORM_CATEGORY_IDENTITY:
gsk_vulkan_clip_init_copy (dest, src);
return TRUE;
case GSK_TRANSFORM_CATEGORY_2D_TRANSLATE:
{
float dx, dy;
gsk_transform_to_translate (transform, &dx, &dy);
gsk_vulkan_clip_init_copy (dest, src);
dest->rect.bounds.origin.x -= dx;
dest->rect.bounds.origin.y -= dy;
}
return TRUE;
case GSK_TRANSFORM_CATEGORY_2D_AFFINE:
{
float dx, dy, scale_x, scale_y;
gsk_transform_to_affine (transform, &scale_x, &scale_y, &dx, &dy);
scale_x = 1. / scale_x;
scale_y = 1. / scale_y;
gsk_vulkan_clip_init_copy (dest, src);
dest->rect.bounds.origin.x = (dest->rect.bounds.origin.x - dx) * scale_x;
dest->rect.bounds.origin.y = (dest->rect.bounds.origin.y - dy) * scale_y;
dest->rect.bounds.size.width *= scale_x;
dest->rect.bounds.size.height *= scale_y;
if (src->type != GSK_VULKAN_CLIP_RECT)
{
dest->rect.corner[0].width *= scale_x;
dest->rect.corner[0].height *= scale_y;
dest->rect.corner[1].width *= scale_x;
dest->rect.corner[1].height *= scale_y;
dest->rect.corner[2].width *= scale_x;
dest->rect.corner[2].height *= scale_y;
dest->rect.corner[3].width *= scale_x;
dest->rect.corner[3].height *= scale_y;
}
}
return TRUE;
case GSK_TRANSFORM_CATEGORY_UNKNOWN:
case GSK_TRANSFORM_CATEGORY_ANY:
case GSK_TRANSFORM_CATEGORY_3D:
case GSK_TRANSFORM_CATEGORY_2D:
default:
return FALSE;
}
}
}
gboolean
gsk_vulkan_clip_may_intersect_rect (const GskVulkanClip *self,
const graphene_point_t *offset,
const graphene_rect_t *rect)
{
graphene_rect_t r = *rect;
r.origin.x += offset->x;
r.origin.y += offset->y;
switch (self->type)
{
default:
g_assert_not_reached();
case GSK_VULKAN_CLIP_ALL_CLIPPED:
return FALSE;
case GSK_VULKAN_CLIP_NONE:
case GSK_VULKAN_CLIP_RECT:
case GSK_VULKAN_CLIP_ROUNDED:
return gsk_rect_intersects (&self->rect.bounds, &r);
}
}
gboolean
gsk_vulkan_clip_contains_rect (const GskVulkanClip *self,
const graphene_point_t *offset,
const graphene_rect_t *rect)
{
graphene_rect_t r = *rect;
r.origin.x += offset->x;
r.origin.y += offset->y;
switch (self->type)
{
default:
g_assert_not_reached();
case GSK_VULKAN_CLIP_ALL_CLIPPED:
return FALSE;
case GSK_VULKAN_CLIP_NONE:
return TRUE;
case GSK_VULKAN_CLIP_RECT:
return graphene_rect_contains_rect (&self->rect.bounds, &r);
case GSK_VULKAN_CLIP_ROUNDED:
return gsk_rounded_rect_contains_rect (&self->rect, &r);
}
}
GskVulkanShaderClip
gsk_vulkan_clip_get_shader_clip (const GskVulkanClip *self,
const graphene_point_t *offset,
const graphene_rect_t *rect)
{
if (gsk_vulkan_clip_contains_rect (self, offset, rect))
return GSK_VULKAN_SHADER_CLIP_NONE;
else if (self->type == GSK_VULKAN_CLIP_RECT)
return GSK_VULKAN_SHADER_CLIP_RECT;
else
return GSK_VULKAN_SHADER_CLIP_ROUNDED;
}

View File

@ -1,72 +0,0 @@
#pragma once
#include <gdk/gdk.h>
#include <graphene.h>
#include <gsk/gskroundedrect.h>
G_BEGIN_DECLS
typedef enum {
GSK_VULKAN_SHADER_CLIP_NONE,
GSK_VULKAN_SHADER_CLIP_RECT,
GSK_VULKAN_SHADER_CLIP_ROUNDED
} GskVulkanShaderClip;
typedef enum {
/* The whole area is clipped, no drawing is necessary.
* This can't be handled by return values because for return
* values we return if clips could even be computed.
*/
GSK_VULKAN_CLIP_ALL_CLIPPED,
/* No clipping is necessary, but the clip rect is set
* to the actual bounds of the underlying framebuffer
*/
GSK_VULKAN_CLIP_NONE,
/* The clip is a rectangular area */
GSK_VULKAN_CLIP_RECT,
/* The clip is a rounded rectangle */
GSK_VULKAN_CLIP_ROUNDED
} GskVulkanClipComplexity;
typedef struct _GskVulkanClip GskVulkanClip;
struct _GskVulkanClip
{
GskVulkanClipComplexity type;
GskRoundedRect rect;
};
void gsk_vulkan_clip_init_empty (GskVulkanClip *clip,
const graphene_rect_t *rect);
void gsk_vulkan_clip_init_copy (GskVulkanClip *self,
const GskVulkanClip *src);
void gsk_vulkan_clip_init_rect (GskVulkanClip *clip,
const graphene_rect_t *rect);
gboolean gsk_vulkan_clip_intersect_rect (GskVulkanClip *dest,
const GskVulkanClip *src,
const graphene_rect_t *rect) G_GNUC_WARN_UNUSED_RESULT;
gboolean gsk_vulkan_clip_intersect_rounded_rect (GskVulkanClip *dest,
const GskVulkanClip *src,
const GskRoundedRect *rounded) G_GNUC_WARN_UNUSED_RESULT;
void gsk_vulkan_clip_scale (GskVulkanClip *dest,
const GskVulkanClip *src,
float scale_x,
float scale_y);
gboolean gsk_vulkan_clip_transform (GskVulkanClip *dest,
const GskVulkanClip *src,
GskTransform *transform,
const graphene_rect_t *viewport) G_GNUC_WARN_UNUSED_RESULT;
gboolean gsk_vulkan_clip_contains_rect (const GskVulkanClip *self,
const graphene_point_t *offset,
const graphene_rect_t *rect) G_GNUC_WARN_UNUSED_RESULT;
gboolean gsk_vulkan_clip_may_intersect_rect (const GskVulkanClip *self,
const graphene_point_t *offset,
const graphene_rect_t *rect) G_GNUC_WARN_UNUSED_RESULT;
GskVulkanShaderClip gsk_vulkan_clip_get_shader_clip (const GskVulkanClip *self,
const graphene_point_t *offset,
const graphene_rect_t *rect);
G_END_DECLS

View File

@ -1,135 +0,0 @@
#include "config.h"
#include "gskvulkancolormatrixopprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanshaderopprivate.h"
#include "vulkan/resources/color-matrix.vert.h"
typedef struct _GskVulkanColorMatrixOp GskVulkanColorMatrixOp;
struct _GskVulkanColorMatrixOp
{
GskVulkanShaderOp op;
graphene_matrix_t color_matrix;
graphene_vec4_t color_offset;
graphene_rect_t rect;
graphene_rect_t tex_rect;
guint32 image_descriptor;
};
static void
gsk_vulkan_color_matrix_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanColorMatrixOp *self = (GskVulkanColorMatrixOp *) op;
print_indent (string, indent);
print_rect (string, &self->rect);
g_string_append (string, "color-matrix ");
print_newline (string);
}
static void
gsk_vulkan_color_matrix_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
GskVulkanColorMatrixOp *self = (GskVulkanColorMatrixOp *) op;
GskVulkanColorMatrixInstance *instance = (GskVulkanColorMatrixInstance *) (data + ((GskVulkanShaderOp *) op)->vertex_offset);
instance->rect[0] = self->rect.origin.x;
instance->rect[1] = self->rect.origin.y;
instance->rect[2] = self->rect.size.width;
instance->rect[3] = self->rect.size.height;
instance->tex_rect[0] = self->tex_rect.origin.x;
instance->tex_rect[1] = self->tex_rect.origin.y;
instance->tex_rect[2] = self->tex_rect.size.width;
instance->tex_rect[3] = self->tex_rect.size.height;
graphene_matrix_to_float (&self->color_matrix, instance->color_matrix);
graphene_vec4_to_float (&self->color_offset, instance->color_offset);
instance->tex_id = self->image_descriptor;
}
static void
gsk_vulkan_color_matrix_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
GskVulkanColorMatrixOp *self = (GskVulkanColorMatrixOp *) op;
GskVulkanShaderOp *shader = (GskVulkanShaderOp *) op;
self->image_descriptor = gsk_vulkan_render_get_image_descriptor (render,
shader->images[0],
GSK_VULKAN_SAMPLER_DEFAULT);
}
static const GskVulkanShaderOpClass GSK_VULKAN_COLOR_MATRIX_OP_CLASS = {
{
GSK_VULKAN_OP_SIZE (GskVulkanColorMatrixOp),
GSK_VULKAN_STAGE_SHADER,
gsk_vulkan_shader_op_finish,
gsk_vulkan_color_matrix_op_print,
gsk_vulkan_shader_op_count_vertex_data,
gsk_vulkan_color_matrix_op_collect_vertex_data,
gsk_vulkan_color_matrix_op_reserve_descriptor_sets,
gsk_vulkan_shader_op_command
},
"color-matrix",
1,
&gsk_vulkan_color_matrix_info,
};
void
gsk_vulkan_color_matrix_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
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;
self = (GskVulkanColorMatrixOp *) gsk_vulkan_shader_op_alloc (render, &GSK_VULKAN_COLOR_MATRIX_OP_CLASS, clip, &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;
}
void
gsk_vulkan_color_matrix_op_opacity (GskVulkanRender *render,
GskVulkanShaderClip clip,
GskVulkanImage *image,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
float opacity)
{
graphene_matrix_t color_matrix;
graphene_vec4_t color_offset;
graphene_matrix_init_from_float (&color_matrix,
(float[16]) {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, opacity
});
graphene_vec4_init (&color_offset, 0.0, 0.0, 0.0, 0.0);
gsk_vulkan_color_matrix_op (render,
clip,
image,
rect,
offset,
tex_rect,
&color_matrix,
&color_offset);
}

View File

@ -1,26 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_color_matrix_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
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);
void gsk_vulkan_color_matrix_op_opacity (GskVulkanRender *render,
GskVulkanShaderClip clip,
GskVulkanImage *image,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
float opacity);
G_END_DECLS

View File

@ -1,91 +0,0 @@
#include "config.h"
#include "gskvulkancoloropprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanshaderopprivate.h"
#include "vulkan/resources/color.vert.h"
typedef struct _GskVulkanColorOp GskVulkanColorOp;
struct _GskVulkanColorOp
{
GskVulkanShaderOp op;
graphene_rect_t rect;
GdkRGBA color;
};
static void
gsk_vulkan_color_op_finish (GskVulkanOp *op)
{
}
static void
gsk_vulkan_color_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanColorOp *self = (GskVulkanColorOp *) op;
print_indent (string, indent);
print_rect (string, &self->rect);
g_string_append (string, "color ");
print_rgba (string, &self->color);
print_newline (string);
}
static void
gsk_vulkan_color_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
GskVulkanColorOp *self = (GskVulkanColorOp *) op;
GskVulkanColorInstance *instance = (GskVulkanColorInstance *) (data + ((GskVulkanShaderOp *) op)->vertex_offset);
instance->rect[0] = self->rect.origin.x;
instance->rect[1] = self->rect.origin.y;
instance->rect[2] = self->rect.size.width;
instance->rect[3] = self->rect.size.height;
instance->color[0] = self->color.red;
instance->color[1] = self->color.green;
instance->color[2] = self->color.blue;
instance->color[3] = self->color.alpha;
}
static void
gsk_vulkan_color_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
}
static const GskVulkanShaderOpClass GSK_VULKAN_COLOR_OP_CLASS = {
{
GSK_VULKAN_OP_SIZE (GskVulkanColorOp),
GSK_VULKAN_STAGE_SHADER,
gsk_vulkan_color_op_finish,
gsk_vulkan_color_op_print,
gsk_vulkan_shader_op_count_vertex_data,
gsk_vulkan_color_op_collect_vertex_data,
gsk_vulkan_color_op_reserve_descriptor_sets,
gsk_vulkan_shader_op_command
},
"color",
0,
&gsk_vulkan_color_info,
};
void
gsk_vulkan_color_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const GdkRGBA *color)
{
GskVulkanColorOp *self;
self = (GskVulkanColorOp *) gsk_vulkan_shader_op_alloc (render, &GSK_VULKAN_COLOR_OP_CLASS, clip, NULL);
graphene_rect_offset_r (rect, offset->x, offset->y, &self->rect);
self->color = *color;
}

View File

@ -1,15 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_color_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const GdkRGBA *color);
G_END_DECLS

View File

@ -1,133 +0,0 @@
#include "config.h"
#include "gskvulkancommandpoolprivate.h"
#include "gskvulkanprivate.h"
struct _GskVulkanCommandPool
{
GdkVulkanContext *vulkan;
VkCommandPool vk_command_pool;
GPtrArray *buffers;
};
GskVulkanCommandPool *
gsk_vulkan_command_pool_new (GdkVulkanContext *context)
{
GskVulkanCommandPool *self;
self = g_new0 (GskVulkanCommandPool, 1);
self->vulkan = g_object_ref (context);
GSK_VK_CHECK (vkCreateCommandPool, gdk_vulkan_context_get_device (context),
&(const VkCommandPoolCreateInfo) {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.queueFamilyIndex = gdk_vulkan_context_get_queue_family_index (self->vulkan),
.flags = 0
},
NULL,
&self->vk_command_pool);
self->buffers = g_ptr_array_new ();
return self;
}
static void
gsk_vulkan_command_pool_free_buffers (GskVulkanCommandPool *self)
{
if (self->buffers->len != 0)
vkFreeCommandBuffers (gdk_vulkan_context_get_device (self->vulkan),
self->vk_command_pool,
self->buffers->len,
(VkCommandBuffer *) self->buffers->pdata);
g_ptr_array_set_size (self->buffers, 0);
}
void
gsk_vulkan_command_pool_free (GskVulkanCommandPool *self)
{
gsk_vulkan_command_pool_free_buffers (self);
g_ptr_array_unref (self->buffers);
vkDestroyCommandPool (gdk_vulkan_context_get_device (self->vulkan),
self->vk_command_pool,
NULL);
g_object_unref (self->vulkan);
g_free (self);
}
void
gsk_vulkan_command_pool_reset (GskVulkanCommandPool *self)
{
gsk_vulkan_command_pool_free_buffers (self);
GSK_VK_CHECK (vkResetCommandPool, gdk_vulkan_context_get_device (self->vulkan),
self->vk_command_pool,
0);
}
VkCommandBuffer
gsk_vulkan_command_pool_get_buffer (GskVulkanCommandPool *self)
{
VkCommandBuffer command_buffer;
GSK_VK_CHECK (vkAllocateCommandBuffers, gdk_vulkan_context_get_device (self->vulkan),
&(VkCommandBufferAllocateInfo) {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.commandPool = self->vk_command_pool,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1,
},
&command_buffer);
g_ptr_array_add (self->buffers, command_buffer);
GSK_VK_CHECK (vkBeginCommandBuffer, command_buffer,
&(VkCommandBufferBeginInfo) {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = 0
});
return command_buffer;
}
void
gsk_vulkan_command_pool_submit_buffer (GskVulkanCommandPool *self,
VkCommandBuffer command_buffer,
gsize wait_semaphore_count,
VkSemaphore *wait_semaphores,
gsize signal_semaphore_count,
VkSemaphore *signal_semaphores,
VkFence fence)
{
VkPipelineStageFlags *wait_semaphore_flags = NULL;
GSK_VK_CHECK (vkEndCommandBuffer, command_buffer);
if (wait_semaphore_count > 0)
{
wait_semaphore_flags = alloca (sizeof (VkPipelineStageFlags) * wait_semaphore_count);
for (int i = 0; i < wait_semaphore_count; i++)
wait_semaphore_flags[i] = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
GSK_VK_CHECK (vkQueueSubmit, gdk_vulkan_context_get_queue (self->vulkan),
1,
&(VkSubmitInfo) {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.waitSemaphoreCount = wait_semaphore_count,
.pWaitSemaphores = wait_semaphores,
.pWaitDstStageMask = wait_semaphore_flags,
.commandBufferCount = 1,
.pCommandBuffers = (VkCommandBuffer[1]) {
command_buffer
},
.signalSemaphoreCount = signal_semaphore_count,
.pSignalSemaphores = signal_semaphores,
},
fence);
}

View File

@ -1,24 +0,0 @@
#pragma once
#include <gdk/gdk.h>
G_BEGIN_DECLS
typedef struct _GskVulkanCommandPool GskVulkanCommandPool;
GskVulkanCommandPool * gsk_vulkan_command_pool_new (GdkVulkanContext *context);
void gsk_vulkan_command_pool_free (GskVulkanCommandPool *self);
void gsk_vulkan_command_pool_reset (GskVulkanCommandPool *self);
VkCommandBuffer gsk_vulkan_command_pool_get_buffer (GskVulkanCommandPool *self);
void gsk_vulkan_command_pool_submit_buffer (GskVulkanCommandPool *self,
VkCommandBuffer buffer,
gsize wait_semaphore_count,
VkSemaphore *wait_semaphores,
gsize signal_semaphores_count,
VkSemaphore *signal_semaphores,
VkFence fence);
G_END_DECLS

View File

@ -1,100 +0,0 @@
#include "config.h"
#include "gskvulkanconvertopprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanshaderopprivate.h"
#include "vulkan/resources/convert.vert.h"
typedef struct _GskVulkanConvertOp GskVulkanConvertOp;
struct _GskVulkanConvertOp
{
GskVulkanShaderOp op;
graphene_rect_t rect;
graphene_rect_t tex_rect;
guint32 image_descriptor;
};
static void
gsk_vulkan_convert_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanConvertOp *self = (GskVulkanConvertOp *) op;
GskVulkanShaderOp *shader = (GskVulkanShaderOp *) op;
print_indent (string, indent);
print_rect (string, &self->rect);
g_string_append (string, "convert ");
print_image (string, shader->images[0]);
print_newline (string);
}
static void
gsk_vulkan_convert_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
GskVulkanConvertOp *self = (GskVulkanConvertOp *) op;
GskVulkanConvertInstance *instance = (GskVulkanConvertInstance *) (data + ((GskVulkanShaderOp *) op)->vertex_offset);
GskVulkanShaderOp *shader = (GskVulkanShaderOp *) op;
instance->rect[0] = self->rect.origin.x;
instance->rect[1] = self->rect.origin.y;
instance->rect[2] = self->rect.size.width;
instance->rect[3] = self->rect.size.height;
instance->tex_rect[0] = self->tex_rect.origin.x;
instance->tex_rect[1] = self->tex_rect.origin.y;
instance->tex_rect[2] = self->tex_rect.size.width;
instance->tex_rect[3] = self->tex_rect.size.height;
instance->tex_id = self->image_descriptor;
instance->postprocess = gsk_vulkan_image_get_postprocess (shader->images[0]);
}
static void
gsk_vulkan_convert_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
GskVulkanConvertOp *self = (GskVulkanConvertOp *) op;
GskVulkanShaderOp *shader = (GskVulkanShaderOp *) op;
self->image_descriptor = gsk_vulkan_render_get_image_descriptor (render, shader->images[0], GSK_VULKAN_SAMPLER_NEAREST);
}
static const GskVulkanShaderOpClass GSK_VULKAN_CONVERT_OP_CLASS = {
{
GSK_VULKAN_OP_SIZE (GskVulkanConvertOp),
GSK_VULKAN_STAGE_SHADER,
gsk_vulkan_shader_op_finish,
gsk_vulkan_convert_op_print,
gsk_vulkan_shader_op_count_vertex_data,
gsk_vulkan_convert_op_collect_vertex_data,
gsk_vulkan_convert_op_reserve_descriptor_sets,
gsk_vulkan_shader_op_command
},
"convert",
1,
&gsk_vulkan_convert_info,
};
void
gsk_vulkan_convert_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
GskVulkanImage *image,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect)
{
GskVulkanConvertOp *self;
self = (GskVulkanConvertOp *) gsk_vulkan_shader_op_alloc (render,
&GSK_VULKAN_CONVERT_OP_CLASS,
clip,
&image);
graphene_rect_offset_r (rect, offset->x, offset->y, &self->rect);
gsk_vulkan_normalize_tex_coords (&self->tex_rect, rect, tex_rect);
}

View File

@ -1,16 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_convert_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
GskVulkanImage *image,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect);
G_END_DECLS

View File

@ -1,119 +0,0 @@
#include "config.h"
#include "gskvulkancrossfadeopprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanshaderopprivate.h"
#include "vulkan/resources/cross-fade.vert.h"
typedef struct _GskVulkanCrossFadeOp GskVulkanCrossFadeOp;
struct _GskVulkanCrossFadeOp
{
GskVulkanShaderOp op;
graphene_rect_t bounds;
float progress;
struct {
graphene_rect_t rect;
graphene_rect_t tex_rect;
guint32 image_descriptor;
} start, end;
};
static void
gsk_vulkan_cross_fade_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanCrossFadeOp *self = (GskVulkanCrossFadeOp *) op;
print_indent (string, indent);
print_rect (string, &self->bounds);
g_string_append_printf (string, "cross-fade %d%% ", (int) (self->progress * 100 + 0.5));
print_newline (string);
}
static void
gsk_vulkan_cross_fade_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
GskVulkanCrossFadeOp *self = (GskVulkanCrossFadeOp *) op;
GskVulkanCrossFadeInstance *instance = (GskVulkanCrossFadeInstance *) (data + ((GskVulkanShaderOp *) op)->vertex_offset);
gsk_rect_to_float (&self->bounds, instance->rect);
gsk_rect_to_float (&self->start.rect, instance->start_rect);
gsk_rect_to_float (&self->end.rect, instance->end_rect);
gsk_rect_to_float (&self->start.tex_rect, instance->start_tex_rect);
gsk_rect_to_float (&self->end.tex_rect, instance->end_tex_rect);
instance->start_tex_id = self->start.image_descriptor;
instance->end_tex_id = self->end.image_descriptor;
instance->progress = self->progress;
}
static void
gsk_vulkan_cross_fade_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
GskVulkanCrossFadeOp *self = (GskVulkanCrossFadeOp *) op;
GskVulkanShaderOp *shader = (GskVulkanShaderOp *) op;
self->start.image_descriptor = gsk_vulkan_render_get_image_descriptor (render,
shader->images[0],
GSK_VULKAN_SAMPLER_DEFAULT);
self->end.image_descriptor = gsk_vulkan_render_get_image_descriptor (render,
shader->images[1],
GSK_VULKAN_SAMPLER_DEFAULT);
}
static const GskVulkanShaderOpClass GSK_VULKAN_CROSS_FADE_OP_CLASS = {
{
GSK_VULKAN_OP_SIZE (GskVulkanCrossFadeOp),
GSK_VULKAN_STAGE_SHADER,
gsk_vulkan_shader_op_finish,
gsk_vulkan_cross_fade_op_print,
gsk_vulkan_shader_op_count_vertex_data,
gsk_vulkan_cross_fade_op_collect_vertex_data,
gsk_vulkan_cross_fade_op_reserve_descriptor_sets,
gsk_vulkan_shader_op_command
},
"cross-fade",
2,
&gsk_vulkan_cross_fade_info,
};
void
gsk_vulkan_cross_fade_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const graphene_rect_t *bounds,
const graphene_point_t *offset,
float progress,
GskVulkanImage *start_image,
const graphene_rect_t *start_rect,
const graphene_rect_t *start_tex_rect,
GskVulkanImage *end_image,
const graphene_rect_t *end_rect,
const graphene_rect_t *end_tex_rect)
{
GskVulkanCrossFadeOp *self;
self = (GskVulkanCrossFadeOp *) gsk_vulkan_shader_op_alloc (render,
&GSK_VULKAN_CROSS_FADE_OP_CLASS,
clip,
(GskVulkanImage *[2]) {
start_image,
end_image
});
graphene_rect_offset_r (bounds, offset->x, offset->y, &self->bounds);
self->progress = progress;
graphene_rect_offset_r (start_rect, offset->x, offset->y, &self->start.rect);
gsk_vulkan_normalize_tex_coords (&self->start.tex_rect, bounds, start_tex_rect);
graphene_rect_offset_r (end_rect, offset->x, offset->y, &self->end.rect);
gsk_vulkan_normalize_tex_coords (&self->end.tex_rect, bounds, end_tex_rect);
}

View File

@ -1,21 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_cross_fade_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const graphene_rect_t *bounds,
const graphene_point_t *offset,
float progress,
GskVulkanImage *start_image,
const graphene_rect_t *start_rect,
const graphene_rect_t *start_tex_rect,
GskVulkanImage *end_image,
const graphene_rect_t *end_rect,
const graphene_rect_t *end_tex_rect);
G_END_DECLS

View File

@ -1,232 +0,0 @@
#include "config.h"
#include "gskvulkandownloadopprivate.h"
#include "gskvulkanprivate.h"
#include "gdk/gdkmemoryformatprivate.h"
static gsize
gsk_vulkan_download_op_count_vertex_data (GskVulkanOp *op,
gsize n_bytes)
{
return n_bytes;
}
static void
gsk_vulkan_download_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
}
static void
gsk_vulkan_download_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
}
static GskVulkanOp *
gsk_vulkan_download_op_command_with_area (GskVulkanOp *op,
GskVulkanRender *render,
VkCommandBuffer command_buffer,
GskVulkanImage *image,
const cairo_rectangle_int_t *area,
GskVulkanBuffer **buffer)
{
gsize stride;
stride = area->width * gdk_memory_format_bytes_per_pixel (gsk_vulkan_image_get_format (image));
*buffer = gsk_vulkan_buffer_new_map (gsk_vulkan_render_get_context (render),
area->height * stride,
GSK_VULKAN_READ);
gsk_vulkan_image_transition (image,
command_buffer,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_ACCESS_TRANSFER_READ_BIT);
vkCmdCopyImageToBuffer (command_buffer,
gsk_vulkan_image_get_vk_image (image),
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
gsk_vulkan_buffer_get_buffer (*buffer),
1,
(VkBufferImageCopy[1]) {
{
.bufferOffset = 0,
.bufferRowLength = area->width,
.bufferImageHeight = area->height,
.imageSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = 1
},
.imageOffset = {
.x = area->x,
.y = area->y,
.z = 0
},
.imageExtent = {
.width = area->width,
.height = area->height,
.depth = 1
}
}
});
vkCmdPipelineBarrier (command_buffer,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_HOST_BIT,
0,
0, NULL,
1, &(VkBufferMemoryBarrier) {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_HOST_READ_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = gsk_vulkan_buffer_get_buffer (*buffer),
.offset = 0,
.size = VK_WHOLE_SIZE,
},
0, NULL);
return op->next;
}
typedef struct _GskVulkanDownloadOp GskVulkanDownloadOp;
struct _GskVulkanDownloadOp
{
GskVulkanOp op;
GskVulkanImage *image;
GskVulkanDownloadFunc func;
gpointer user_data;
GskVulkanBuffer *buffer;
};
static void
gsk_vulkan_download_op_finish (GskVulkanOp *op)
{
GskVulkanDownloadOp *self = (GskVulkanDownloadOp *) op;
guchar *data;
gsize stride;
data = gsk_vulkan_buffer_map (self->buffer);
stride = gsk_vulkan_image_get_width (self->image) *
gdk_memory_format_bytes_per_pixel (gsk_vulkan_image_get_format (self->image));
self->func (self->user_data,
gsk_vulkan_image_get_format (self->image),
data,
gsk_vulkan_image_get_width (self->image),
gsk_vulkan_image_get_height (self->image),
stride);
gsk_vulkan_buffer_unmap (self->buffer);
g_object_unref (self->image);
g_clear_pointer (&self->buffer, gsk_vulkan_buffer_free);
}
static void
gsk_vulkan_download_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanDownloadOp *self = (GskVulkanDownloadOp *) op;
print_indent (string, indent);
g_string_append (string, "download ");
print_image (string, self->image);
print_newline (string);
}
static GskVulkanOp *
gsk_vulkan_download_op_command (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer)
{
GskVulkanDownloadOp *self = (GskVulkanDownloadOp *) op;
return gsk_vulkan_download_op_command_with_area (op,
render,
command_buffer,
self->image,
&(cairo_rectangle_int_t) {
0, 0,
gsk_vulkan_image_get_width (self->image),
gsk_vulkan_image_get_height (self->image)
},
&self->buffer);
}
static const GskVulkanOpClass GSK_VULKAN_DOWNLOAD_OP_CLASS = {
GSK_VULKAN_OP_SIZE (GskVulkanDownloadOp),
GSK_VULKAN_STAGE_COMMAND,
gsk_vulkan_download_op_finish,
gsk_vulkan_download_op_print,
gsk_vulkan_download_op_count_vertex_data,
gsk_vulkan_download_op_collect_vertex_data,
gsk_vulkan_download_op_reserve_descriptor_sets,
gsk_vulkan_download_op_command
};
void
gsk_vulkan_download_op (GskVulkanRender *render,
GskVulkanImage *image,
GskVulkanDownloadFunc func,
gpointer user_data)
{
GskVulkanDownloadOp *self;
self = (GskVulkanDownloadOp *) gsk_vulkan_op_alloc (render, &GSK_VULKAN_DOWNLOAD_OP_CLASS);
self->image = g_object_ref (image);
self->func = func,
self->user_data = user_data;
}
static void
gsk_vulkan_download_save_png_cb (gpointer filename,
GdkMemoryFormat format,
const guchar *data,
int width,
int height,
gsize stride)
{
GdkTexture *texture;
GBytes *bytes;
bytes = g_bytes_new_static (data, stride * height);
texture = gdk_memory_texture_new (width, height,
format,
bytes,
stride);
gdk_texture_save_to_png (texture, filename);
g_object_unref (texture);
g_bytes_unref (bytes);
g_free (filename);
}
void
gsk_vulkan_download_png_op (GskVulkanRender *render,
GskVulkanImage *image,
const char *filename_format,
...)
{
va_list args;
char *filename;
va_start (args, filename_format);
filename = g_strdup_vprintf (filename_format, args);
va_end (args);
gsk_vulkan_download_op (render,
image,
gsk_vulkan_download_save_png_cb,
filename);
}

View File

@ -1,18 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_download_op (GskVulkanRender *render,
GskVulkanImage *image,
GskVulkanDownloadFunc func,
gpointer user_data);
void gsk_vulkan_download_png_op (GskVulkanRender *render,
GskVulkanImage *image,
const char *filename_format,
...) G_GNUC_PRINTF(3, 4);
G_END_DECLS

View File

@ -1,415 +0,0 @@
#include "config.h"
#include "gskvulkanglyphcacheprivate.h"
#include "gskvulkanimageprivate.h"
#include "gskvulkanuploadopprivate.h"
#include "gskdebugprivate.h"
#include "gskprivate.h"
#include "gskrendererprivate.h"
#include <graphene.h>
/* Parameters for our cache eviction strategy.
*
* Each cached glyph has an age that gets reset every time a cached glyph gets used.
* Glyphs that have not been used for the MAX_AGE frames are considered old. We keep
* count of the pixels of each atlas that are taken up by old glyphs. We check the
* fraction of old pixels every CHECK_INTERVAL frames, and if it is above MAX_OLD, then
* we drop the atlas an all the glyphs contained in it from the cache.
*/
#define MAX_AGE 60
#define CHECK_INTERVAL 10
#define MAX_OLD 0.333
#define PADDING 1
typedef struct {
GskVulkanImage *image;
int width, height;
int x, y, y0;
guint old_pixels;
} Atlas;
struct _GskVulkanGlyphCache {
GObject parent_instance;
GdkVulkanContext *vulkan;
GskRenderer *renderer;
GHashTable *hash_table;
GPtrArray *atlases;
guint64 timestamp;
};
struct _GskVulkanGlyphCacheClass {
GObjectClass parent_class;
};
G_DEFINE_TYPE (GskVulkanGlyphCache, gsk_vulkan_glyph_cache, G_TYPE_OBJECT)
static guint glyph_cache_hash (gconstpointer v);
static gboolean glyph_cache_equal (gconstpointer v1,
gconstpointer v2);
static void glyph_cache_key_free (gpointer v);
static void glyph_cache_value_free (gpointer v);
static Atlas *
create_atlas (GskVulkanGlyphCache *cache)
{
Atlas *atlas;
atlas = g_new0 (Atlas, 1);
atlas->width = 512;
atlas->height = 512;
atlas->y0 = 0;
atlas->y = 0;
atlas->x = 0;
atlas->image = NULL;
atlas->image = gsk_vulkan_image_new_for_atlas (cache->vulkan, atlas->width, atlas->height);
return atlas;
}
static void
free_atlas (gpointer v)
{
Atlas *atlas = v;
g_clear_object (&atlas->image);
g_free (atlas);
}
static void
gsk_vulkan_glyph_cache_init (GskVulkanGlyphCache *cache)
{
cache->hash_table = g_hash_table_new_full (glyph_cache_hash, glyph_cache_equal,
glyph_cache_key_free, glyph_cache_value_free);
cache->atlases = g_ptr_array_new_with_free_func (free_atlas);
}
static void
gsk_vulkan_glyph_cache_finalize (GObject *object)
{
GskVulkanGlyphCache *cache = GSK_VULKAN_GLYPH_CACHE (object);
g_ptr_array_unref (cache->atlases);
g_hash_table_unref (cache->hash_table);
G_OBJECT_CLASS (gsk_vulkan_glyph_cache_parent_class)->finalize (object);
}
static void
gsk_vulkan_glyph_cache_class_init (GskVulkanGlyphCacheClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gsk_vulkan_glyph_cache_finalize;
}
typedef struct {
PangoFont *font;
PangoGlyph glyph;
guint xshift;
guint yshift;
guint scale; /* times 1024 */
} GlyphCacheKey;
static gboolean
glyph_cache_equal (gconstpointer v1, gconstpointer v2)
{
const GlyphCacheKey *key1 = v1;
const GlyphCacheKey *key2 = v2;
return key1->font == key2->font &&
key1->glyph == key2->glyph &&
key1->xshift == key2->xshift &&
key1->yshift == key2->yshift &&
key1->scale == key2->scale;
}
static guint
glyph_cache_hash (gconstpointer v)
{
const GlyphCacheKey *key = v;
return GPOINTER_TO_UINT (key->font) ^ key->glyph ^ (key->xshift << 24) ^ (key->yshift << 26) ^ key->scale;
}
static void
glyph_cache_key_free (gpointer v)
{
GlyphCacheKey *f = v;
g_object_unref (f->font);
g_free (f);
}
static void
glyph_cache_value_free (gpointer v)
{
g_free (v);
}
static void
add_to_cache (GskVulkanGlyphCache *cache,
GskVulkanRender *render,
GlyphCacheKey *key,
GskVulkanCachedGlyph *value)
{
Atlas *atlas;
int i;
int width = ceil (value->draw_width * key->scale / 1024.0);
int height = ceil (value->draw_height * key->scale / 1024.0);
int width_with_padding = width + 2 * PADDING;
int height_with_padding = height + 2 * PADDING;
for (i = 0; i < cache->atlases->len; i++)
{
int x, y, y0;
atlas = g_ptr_array_index (cache->atlases, i);
x = atlas->x;
y = atlas->y;
y0 = atlas->y0;
if (atlas->x + width_with_padding >= atlas->width)
{
/* start a new row */
y0 = y + PADDING;
x = PADDING;
}
if (y0 + height_with_padding >= atlas->height)
continue;
atlas->y0 = y0;
atlas->x = x;
atlas->y = y;
break;
}
if (i == cache->atlases->len)
{
atlas = create_atlas (cache);
g_ptr_array_add (cache->atlases, atlas);
}
value->atlas_image = atlas->image;
value->atlas_x = atlas->x;
value->atlas_y = atlas->y0;
value->tx = (float)(atlas->x + PADDING) / atlas->width;
value->ty = (float)(atlas->y0 + PADDING) / atlas->height;
value->tw = (float)width / atlas->width;
value->th = (float)height / atlas->height;
atlas->x = atlas->x + width_with_padding;
atlas->y = MAX (atlas->y, atlas->y0 + height_with_padding);
gsk_vulkan_upload_glyph_op (render,
atlas->image,
&(cairo_rectangle_int_t) {
.x = value->atlas_x,
.y = value->atlas_y,
.width = width_with_padding,
.height = height_with_padding
},
key->font,
&(PangoGlyphInfo) {
.glyph = key->glyph,
.geometry.width = value->draw_width * PANGO_SCALE,
.geometry.x_offset = (0.25 * key->xshift - value->draw_x) * PANGO_SCALE,
.geometry.y_offset = (0.25 * key->yshift - value->draw_y) * PANGO_SCALE
},
(float) key->scale / PANGO_SCALE);
#ifdef G_ENABLE_DEBUG
if (GSK_DEBUG_CHECK (GLYPH_CACHE))
{
g_print ("Glyph cache:\n");
for (i = 0; i < cache->atlases->len; i++)
{
atlas = g_ptr_array_index (cache->atlases, i);
g_print ("\tAtlas %d (%dx%d): %.2g%% old pixels, filled to %d, %d / %d\n",
i, atlas->width, atlas->height,
100.0 * (double)atlas->old_pixels / (double)(atlas->width * atlas->height),
atlas->x, atlas->y0, atlas->y);
}
}
#endif
}
GskVulkanGlyphCache *
gsk_vulkan_glyph_cache_new (GdkVulkanContext *vulkan)
{
GskVulkanGlyphCache *cache;
cache = GSK_VULKAN_GLYPH_CACHE (g_object_new (GSK_TYPE_VULKAN_GLYPH_CACHE, NULL));
cache->vulkan = vulkan;
g_ptr_array_add (cache->atlases, create_atlas (cache));
return cache;
}
#define PHASE(x) ((x % PANGO_SCALE) * 4 / PANGO_SCALE)
GskVulkanCachedGlyph *
gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache,
GskVulkanRender *render,
PangoFont *font,
PangoGlyph glyph,
int x,
int y,
float scale)
{
GlyphCacheKey lookup_key;
GskVulkanCachedGlyph *value;
guint xshift;
guint yshift;
xshift = PHASE (x);
yshift = PHASE (y);
lookup_key.font = font;
lookup_key.glyph = glyph;
lookup_key.xshift = xshift;
lookup_key.yshift = yshift;
lookup_key.scale = (guint)(scale * 1024);
value = g_hash_table_lookup (cache->hash_table, &lookup_key);
if (value)
{
if (cache->timestamp - value->timestamp >= MAX_AGE)
{
Atlas *atlas = g_ptr_array_index (cache->atlases, value->texture_index);
atlas->old_pixels -= value->draw_width * value->draw_height;
value->timestamp = cache->timestamp;
}
}
if (value == NULL)
{
GlyphCacheKey *key;
PangoRectangle ink_rect;
key = g_new (GlyphCacheKey, 1);
value = g_new0 (GskVulkanCachedGlyph, 1);
pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL);
pango_extents_to_pixels (&ink_rect, NULL);
ink_rect.x -= 1;
ink_rect.y -= 1;
ink_rect.width += 2;
ink_rect.height += 2;
value->draw_x = ink_rect.x;
value->draw_y = ink_rect.y;
value->draw_width = ink_rect.width;
value->draw_height = ink_rect.height;
value->timestamp = cache->timestamp;
key->font = g_object_ref (font);
key->glyph = glyph;
key->xshift = xshift;
key->yshift = yshift;
key->scale = (guint)(scale * 1024);
if (ink_rect.width > 0 && ink_rect.height > 0)
add_to_cache (cache, render, key, value);
g_hash_table_insert (cache->hash_table, key, value);
}
return value;
}
void
gsk_vulkan_glyph_cache_begin_frame (GskVulkanGlyphCache *cache)
{
int i, j;
guint *drops;
guint *shifts;
guint len;
GHashTableIter iter;
GlyphCacheKey *key;
GskVulkanCachedGlyph *value;
G_GNUC_UNUSED guint dropped = 0;
cache->timestamp++;
if (cache->timestamp % CHECK_INTERVAL != 0)
return;
len = cache->atlases->len;
/* look for glyphs that have grown old since last time */
g_hash_table_iter_init (&iter, cache->hash_table);
while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
{
guint age;
age = cache->timestamp - value->timestamp;
if (MAX_AGE <= age && age < MAX_AGE + CHECK_INTERVAL)
{
Atlas *atlas = g_ptr_array_index (cache->atlases, value->texture_index);
atlas->old_pixels += value->draw_width * value->draw_height;
}
}
drops = g_alloca (sizeof (guint) * len);
shifts = g_alloca (sizeof (guint) * len);
for (i = 0; i < len; i++)
{
drops[i] = 0;
shifts[i] = i;
}
/* look for atlases to drop, and create a mapping of updated texture indices */
for (i = cache->atlases->len - 1; i >= 0; i--)
{
Atlas *atlas = g_ptr_array_index (cache->atlases, i);
if (atlas->old_pixels > MAX_OLD * atlas->width * atlas->height)
{
GSK_DEBUG (GLYPH_CACHE,
"Dropping atlas %d (%g.2%% old)",
i, 100.0 * (double)atlas->old_pixels / (double)(atlas->width * atlas->height));
g_ptr_array_remove_index (cache->atlases, i);
drops[i] = 1;
for (j = i; j + 1 < len; j++)
shifts[j + 1] = shifts[j];
}
}
/* no atlas dropped, we're done */
if (len == cache->atlases->len)
return;
/* purge glyphs and update texture indices */
g_hash_table_iter_init (&iter, cache->hash_table);
while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
{
if (drops[value->texture_index])
{
dropped++;
g_hash_table_iter_remove (&iter);
}
else
{
value->texture_index = shifts[value->texture_index];
}
}
GSK_DEBUG (GLYPH_CACHE, "Dropped %d glyphs", dropped);
}

View File

@ -1,46 +0,0 @@
#pragma once
#include <pango/pango.h>
#include "gskvulkanimageprivate.h"
#include "gskvulkanprivate.h"
G_BEGIN_DECLS
#define GSK_TYPE_VULKAN_GLYPH_CACHE (gsk_vulkan_glyph_cache_get_type ())
G_DECLARE_FINAL_TYPE(GskVulkanGlyphCache, gsk_vulkan_glyph_cache, GSK, VULKAN_GLYPH_CACHE, GObject)
typedef struct
{
guint texture_index;
float tx;
float ty;
float tw;
float th;
int draw_x;
int draw_y;
int draw_width;
int draw_height;
GskVulkanImage *atlas_image;
int atlas_x;
int atlas_y;
guint64 timestamp;
} GskVulkanCachedGlyph;
GskVulkanGlyphCache *gsk_vulkan_glyph_cache_new (GdkVulkanContext *vulkan);
GskVulkanCachedGlyph *gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache,
GskVulkanRender *render,
PangoFont *font,
PangoGlyph glyph,
int x,
int y,
float scale);
void gsk_vulkan_glyph_cache_begin_frame (GskVulkanGlyphCache *cache);

View File

@ -1,93 +0,0 @@
#include "config.h"
#include "gskvulkanglyphopprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanshaderopprivate.h"
#include "vulkan/resources/glyph.vert.h"
typedef struct _GskVulkanGlyphOp GskVulkanGlyphOp;
struct _GskVulkanGlyphOp
{
GskVulkanShaderOp op;
GskVulkanImage *image;
graphene_rect_t rect;
graphene_rect_t tex_rect;
GdkRGBA color;
guint32 image_descriptor;
};
static void
gsk_vulkan_glyph_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanGlyphOp *self = (GskVulkanGlyphOp *) op;
print_indent (string, indent);
print_rect (string, &self->rect);
g_string_append (string, "glyph ");
print_rgba (string, &self->color);
print_newline (string);
}
static void
gsk_vulkan_glyph_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
GskVulkanGlyphOp *self = (GskVulkanGlyphOp *) op;
GskVulkanGlyphInstance *instance = (GskVulkanGlyphInstance *) (data + ((GskVulkanShaderOp *) op)->vertex_offset);
gsk_rect_to_float (&self->rect, instance->rect);
gsk_rect_to_float (&self->tex_rect, instance->tex_rect);
instance->tex_id = self->image_descriptor;
gsk_vulkan_rgba_to_float (&self->color, instance->color);
}
static void
gsk_vulkan_glyph_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
GskVulkanGlyphOp *self = (GskVulkanGlyphOp *) op;
GskVulkanShaderOp *shader = (GskVulkanShaderOp *) op;
self->image_descriptor = gsk_vulkan_render_get_image_descriptor (render, shader->images[0], GSK_VULKAN_SAMPLER_DEFAULT);
}
static const GskVulkanShaderOpClass GSK_VULKAN_GLYPH_OP_CLASS = {
{
GSK_VULKAN_OP_SIZE (GskVulkanGlyphOp),
GSK_VULKAN_STAGE_SHADER,
gsk_vulkan_shader_op_finish,
gsk_vulkan_glyph_op_print,
gsk_vulkan_shader_op_count_vertex_data,
gsk_vulkan_glyph_op_collect_vertex_data,
gsk_vulkan_glyph_op_reserve_descriptor_sets,
gsk_vulkan_shader_op_command
},
"glyph",
1,
&gsk_vulkan_glyph_info,
};
void
gsk_vulkan_glyph_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
GskVulkanImage *image,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
const GdkRGBA *color)
{
GskVulkanGlyphOp *self;
self = (GskVulkanGlyphOp *) gsk_vulkan_shader_op_alloc (render, &GSK_VULKAN_GLYPH_OP_CLASS, clip, &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 = *color;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_glyph_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
GskVulkanImage *image,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect,
const GdkRGBA *color);
G_END_DECLS

View File

@ -1,915 +0,0 @@
#include "config.h"
#include "gskvulkanimageprivate.h"
#include "gskvulkanbufferprivate.h"
#include "gskvulkanmemoryprivate.h"
#include "gskvulkanprivate.h"
#include "gdk/gdkmemoryformatprivate.h"
#include <string.h>
struct _GskVulkanImage
{
GObject parent_instance;
GdkVulkanContext *vulkan;
GdkMemoryFormat format;
VkFormat vk_format;
gsize width;
gsize height;
VkImageTiling vk_tiling;
VkImageUsageFlags vk_usage;
VkImage vk_image;
VkImageView vk_image_view;
VkFramebuffer vk_framebuffer;
GskVulkanImagePostprocess postprocess;
VkPipelineStageFlags vk_pipeline_stage;
VkImageLayout vk_image_layout;
VkAccessFlags vk_access;
GskVulkanMemory *memory;
};
G_DEFINE_TYPE (GskVulkanImage, gsk_vulkan_image, G_TYPE_OBJECT)
typedef struct _GskMemoryFormatInfo GskMemoryFormatInfo;
struct _GskMemoryFormatInfo
{
VkFormat format;
VkComponentMapping components;
GskVulkanImagePostprocess postprocess;
};
static const GskMemoryFormatInfo *
gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
{
#define SWIZZLE(a, b, c, d) { VK_COMPONENT_SWIZZLE_ ## a, VK_COMPONENT_SWIZZLE_ ## b, VK_COMPONENT_SWIZZLE_ ## c, VK_COMPONENT_SWIZZLE_ ## d }
#define DEFAULT_SWIZZLE SWIZZLE (R, G, B, A)
switch (format)
{
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_B8G8R8A8_UNORM, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(B, G, R, A), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(G, B, A, R), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8B8A8_UNORM, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(A, B, G, R), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_B8G8R8A8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_B8G8R8A8_UNORM, DEFAULT_SWIZZLE, GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(B, G, R, A), GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_A8R8G8B8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(G, B, A, R), GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R8G8B8A8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8B8A8_UNORM, DEFAULT_SWIZZLE, GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_A8B8G8R8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(A, B, G, R), GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_B8G8R8X8:
case GDK_MEMORY_X8R8G8B8:
case GDK_MEMORY_R8G8B8X8:
case GDK_MEMORY_X8B8G8R8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R8G8B8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8B8_UNORM, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_B8G8R8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_B8G8R8_UNORM, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_R8G8B8_UNORM, SWIZZLE(B, G, R, A), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R16G16B16:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16B16_UNORM, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16B16A16_UNORM, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R16G16B16A16:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16B16A16_UNORM, DEFAULT_SWIZZLE, GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R16G16B16_FLOAT:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16B16_SFLOAT, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16B16A16_SFLOAT, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R16G16B16A16_FLOAT:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16B16A16_SFLOAT, DEFAULT_SWIZZLE, GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R32G32B32_FLOAT:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R32G32B32_SFLOAT, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R32G32B32A32_SFLOAT, DEFAULT_SWIZZLE, 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_R32G32B32A32_FLOAT:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R32G32B32A32_SFLOAT, DEFAULT_SWIZZLE, GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_G8A8_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8_UNORM, SWIZZLE (R, R, R, G), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_G8A8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8G8_UNORM, SWIZZLE (R, R, R, G), GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_G8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8_UNORM, SWIZZLE (R, R, R, ONE), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_G16A16_PREMULTIPLIED:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16_UNORM, SWIZZLE (R, R, R, G), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_G16A16:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16G16_UNORM, SWIZZLE (R, R, R, G), GSK_VULKAN_IMAGE_PREMULTIPLY },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_G16:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16_UNORM, SWIZZLE (R, R, R, ONE), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_A8:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R8_UNORM, SWIZZLE (R, R, R, R), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_A16:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16_UNORM, SWIZZLE (R, R, R, R), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_A16_FLOAT:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R16_SFLOAT, SWIZZLE (R, R, R, R), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_A32_FLOAT:
{
static const GskMemoryFormatInfo info[] = {
{ VK_FORMAT_R32_SFLOAT, SWIZZLE (R, R, R, R), 0 },
{ VK_FORMAT_UNDEFINED }
};
return info;
}
case GDK_MEMORY_N_FORMATS:
default:
g_assert_not_reached ();
return NULL;
}
#undef DEFAULT_SWIZZLE
#undef SWIZZLE
}
static GdkMemoryFormat
gsk_memory_format_get_fallback (GdkMemoryFormat format)
{
switch (format)
{
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
case GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
case GDK_MEMORY_B8G8R8A8:
case GDK_MEMORY_A8R8G8B8:
case GDK_MEMORY_R8G8B8A8:
case GDK_MEMORY_A8B8G8R8:
case GDK_MEMORY_R8G8B8:
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
case GDK_MEMORY_B8G8R8X8:
case GDK_MEMORY_X8R8G8B8:
case GDK_MEMORY_R8G8B8X8:
case GDK_MEMORY_X8B8G8R8:
case GDK_MEMORY_B8G8R8:
return GDK_MEMORY_R8G8B8;
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
return GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
case GDK_MEMORY_R16G16B16:
case GDK_MEMORY_R16G16B16A16:
return GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
return GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
case GDK_MEMORY_R16G16B16_FLOAT:
case GDK_MEMORY_R16G16B16A16_FLOAT:
return GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
case GDK_MEMORY_R32G32B32_FLOAT:
case GDK_MEMORY_R32G32B32A32_FLOAT:
return GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
case GDK_MEMORY_G8A8_PREMULTIPLIED:
case GDK_MEMORY_G8A8:
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
case GDK_MEMORY_G8:
return GDK_MEMORY_R8G8B8;
case GDK_MEMORY_G16A16_PREMULTIPLIED:
case GDK_MEMORY_G16A16:
return GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
case GDK_MEMORY_G16:
return GDK_MEMORY_R16G16B16;
case GDK_MEMORY_A8:
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
case GDK_MEMORY_A16:
return GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
case GDK_MEMORY_A16_FLOAT:
return GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
case GDK_MEMORY_A32_FLOAT:
return GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
case GDK_MEMORY_N_FORMATS:
default:
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
}
}
static gboolean
gsk_vulkan_context_supports_format (GdkVulkanContext *context,
VkFormat format,
VkImageTiling tiling,
VkImageUsageFlags usage,
gsize width,
gsize height)
{
VkFormatProperties properties;
VkImageFormatProperties image_properties;
VkFormatFeatureFlags features, required;
VkResult res;
vkGetPhysicalDeviceFormatProperties (gdk_vulkan_context_get_physical_device (context),
format,
&properties);
switch ((int) tiling)
{
case VK_IMAGE_TILING_OPTIMAL:
features = properties.optimalTilingFeatures;
break;
case VK_IMAGE_TILING_LINEAR:
features = properties.optimalTilingFeatures;
break;
default:
return FALSE;
}
required = 0;
if (usage & VK_IMAGE_USAGE_SAMPLED_BIT)
required |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
required |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
if ((features & required) != required)
return FALSE;
res = vkGetPhysicalDeviceImageFormatProperties (gdk_vulkan_context_get_physical_device (context),
format,
VK_IMAGE_TYPE_2D,
tiling,
usage,
0,
&image_properties);
if (res != VK_SUCCESS)
return FALSE;
if (image_properties.maxExtent.width < width ||
image_properties.maxExtent.height < height)
return FALSE;
return TRUE;
}
static void
gsk_vulkan_image_create_view (GskVulkanImage *self,
const GskMemoryFormatInfo *format)
{
GSK_VK_CHECK (vkCreateImageView, gdk_vulkan_context_get_device (self->vulkan),
&(VkImageViewCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.image = self->vk_image,
.viewType = VK_IMAGE_VIEW_TYPE_2D,
.format = format->format,
.components = format->components,
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
},
},
NULL,
&self->vk_image_view);
}
static GskVulkanImage *
gsk_vulkan_image_new (GdkVulkanContext *context,
GdkMemoryFormat format,
gsize width,
gsize height,
GskVulkanImagePostprocess allowed_postprocess,
VkImageTiling tiling,
VkImageUsageFlags usage,
VkPipelineStageFlags stage,
VkImageLayout layout,
VkAccessFlags access,
VkMemoryPropertyFlags memory)
{
VkMemoryRequirements requirements;
GskVulkanImage *self;
const GskMemoryFormatInfo *vk_format;
g_assert (width > 0 && height > 0);
while (TRUE)
{
for (vk_format = gsk_memory_format_get_vk_format_infos (format);
vk_format->format != VK_FORMAT_UNDEFINED;
vk_format++)
{
if (vk_format->postprocess & ~allowed_postprocess)
continue;
if (gsk_vulkan_context_supports_format (context,
vk_format->format,
tiling, usage,
width, height))
break;
if (tiling != VK_IMAGE_TILING_OPTIMAL &&
gsk_vulkan_context_supports_format (context,
vk_format->format,
VK_IMAGE_TILING_OPTIMAL, usage,
width, height))
{
tiling = VK_IMAGE_TILING_OPTIMAL;
break;
}
}
if (vk_format->format != VK_FORMAT_UNDEFINED)
break;
format = gsk_memory_format_get_fallback (format);
}
self = g_object_new (GSK_TYPE_VULKAN_IMAGE, NULL);
self->vulkan = g_object_ref (context);
self->format = format;
self->vk_format = vk_format->format;
self->postprocess = vk_format->postprocess;
self->width = width;
self->height = height;
self->vk_tiling = tiling;
self->vk_usage = usage;
self->vk_pipeline_stage = stage;
self->vk_image_layout = layout;
self->vk_access = access;
GSK_VK_CHECK (vkCreateImage, gdk_vulkan_context_get_device (context),
&(VkImageCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.flags = 0,
.imageType = VK_IMAGE_TYPE_2D,
.format = vk_format->format,
.extent = { width, height, 1 },
.mipLevels = 1,
.arrayLayers = 1,
.samples = VK_SAMPLE_COUNT_1_BIT,
.tiling = tiling,
.usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.initialLayout = self->vk_image_layout,
},
NULL,
&self->vk_image);
vkGetImageMemoryRequirements (gdk_vulkan_context_get_device (context),
self->vk_image,
&requirements);
self->memory = gsk_vulkan_memory_new (context,
requirements.memoryTypeBits,
memory,
requirements.size);
GSK_VK_CHECK (vkBindImageMemory, gdk_vulkan_context_get_device (context),
self->vk_image,
gsk_vulkan_memory_get_device_memory (self->memory),
0);
gsk_vulkan_image_create_view (self, vk_format);
return self;
}
GskVulkanImage *
gsk_vulkan_image_new_for_upload (GdkVulkanContext *context,
GdkMemoryFormat format,
gsize width,
gsize height)
{
GskVulkanImage *self;
self = gsk_vulkan_image_new (context,
format,
width,
height,
-1,
VK_IMAGE_TILING_LINEAR,
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_IMAGE_LAYOUT_PREINITIALIZED,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
return self;
}
static gboolean
gsk_vulkan_image_can_map (GskVulkanImage *self)
{
if (GSK_DEBUG_CHECK (STAGING))
return FALSE;
if (self->vk_tiling != VK_IMAGE_TILING_LINEAR)
return FALSE;
if (self->vk_image_layout != VK_IMAGE_LAYOUT_PREINITIALIZED &&
self->vk_image_layout != VK_IMAGE_LAYOUT_GENERAL)
return FALSE;
return gsk_vulkan_memory_can_map (self->memory, TRUE);
}
guchar *
gsk_vulkan_image_try_map (GskVulkanImage *self,
gsize *out_stride)
{
VkImageSubresource image_res;
VkSubresourceLayout image_layout;
guchar *result;
if (!gsk_vulkan_image_can_map (self))
return NULL;
result = gsk_vulkan_memory_map (self->memory);
if (result == NULL)
return NULL;
image_res.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
image_res.mipLevel = 0;
image_res.arrayLayer = 0;
vkGetImageSubresourceLayout (gdk_vulkan_context_get_device (self->vulkan),
self->vk_image, &image_res, &image_layout);
*out_stride = image_layout.rowPitch;
return result + image_layout.offset;
}
void
gsk_vulkan_image_unmap (GskVulkanImage *self)
{
gsk_vulkan_memory_unmap (self->memory);
}
GskVulkanImage *
gsk_vulkan_image_new_for_swapchain (GdkVulkanContext *context,
VkImage image,
VkFormat format,
gsize width,
gsize height)
{
GskVulkanImage *self;
self = g_object_new (GSK_TYPE_VULKAN_IMAGE, NULL);
self->vulkan = g_object_ref (context);
self->width = width;
self->height = height;
self->vk_tiling = VK_IMAGE_TILING_OPTIMAL;
self->vk_image = image;
self->vk_format = format;
self->vk_pipeline_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
self->vk_image_layout = VK_IMAGE_LAYOUT_UNDEFINED;
self->vk_access = 0;
gsk_vulkan_image_create_view (self,
&(GskMemoryFormatInfo) {
format,
{ VK_COMPONENT_SWIZZLE_R,
VK_COMPONENT_SWIZZLE_G,
VK_COMPONENT_SWIZZLE_B,
VK_COMPONENT_SWIZZLE_A
}
});
return self;
}
GskVulkanImage *
gsk_vulkan_image_new_for_atlas (GdkVulkanContext *context,
gsize width,
gsize height)
{
GskVulkanImage *self;
self = gsk_vulkan_image_new (context,
GDK_MEMORY_DEFAULT,
width,
height,
0,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_IMAGE_LAYOUT_UNDEFINED,
0,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
return self;
}
GskVulkanImage *
gsk_vulkan_image_new_for_offscreen (GdkVulkanContext *context,
GdkMemoryFormat preferred_format,
gsize width,
gsize height)
{
GskVulkanImage *self;
self = gsk_vulkan_image_new (context,
preferred_format,
width,
height,
0,
VK_IMAGE_TILING_LINEAR,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
return self;
}
static void
gsk_vulkan_image_finalize (GObject *object)
{
GskVulkanImage *self = GSK_VULKAN_IMAGE (object);
VkDevice device;
device = gdk_vulkan_context_get_device (self->vulkan);
if (self->vk_framebuffer != VK_NULL_HANDLE)
vkDestroyFramebuffer (device, self->vk_framebuffer, NULL);
if (self->vk_image_view != VK_NULL_HANDLE)
vkDestroyImageView (device, self->vk_image_view, NULL);
/* memory is NULL for for_swapchain() images, where we don't own
* the VkImage */
if (self->memory)
vkDestroyImage (device, self->vk_image, NULL);
g_clear_pointer (&self->memory, gsk_vulkan_memory_free);
g_object_unref (self->vulkan);
G_OBJECT_CLASS (gsk_vulkan_image_parent_class)->finalize (object);
}
static void
gsk_vulkan_image_class_init (GskVulkanImageClass *klass)
{
G_OBJECT_CLASS (klass)->finalize = gsk_vulkan_image_finalize;
}
static void
gsk_vulkan_image_init (GskVulkanImage *self)
{
}
VkFramebuffer
gsk_vulkan_image_get_framebuffer (GskVulkanImage *self,
VkRenderPass render_pass)
{
if (self->vk_framebuffer)
return self->vk_framebuffer;
GSK_VK_CHECK (vkCreateFramebuffer, gdk_vulkan_context_get_device (self->vulkan),
&(VkFramebufferCreateInfo) {
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
.renderPass = render_pass,
.attachmentCount = 1,
.pAttachments = (VkImageView[1]) {
self->vk_image_view,
},
.width = self->width,
.height = self->height,
.layers = 1
},
NULL,
&self->vk_framebuffer);
return self->vk_framebuffer;
}
gsize
gsk_vulkan_image_get_width (GskVulkanImage *self)
{
return self->width;
}
gsize
gsk_vulkan_image_get_height (GskVulkanImage *self)
{
return self->height;
}
GskVulkanImagePostprocess
gsk_vulkan_image_get_postprocess (GskVulkanImage *self)
{
return self->postprocess;
}
VkImage
gsk_vulkan_image_get_vk_image (GskVulkanImage *self)
{
return self->vk_image;
}
VkImageView
gsk_vulkan_image_get_image_view (GskVulkanImage *self)
{
return self->vk_image_view;
}
VkPipelineStageFlags
gsk_vulkan_image_get_vk_pipeline_stage (GskVulkanImage *self)
{
return self->vk_pipeline_stage;
}
VkImageLayout
gsk_vulkan_image_get_vk_image_layout (GskVulkanImage *self)
{
return self->vk_image_layout;
}
VkAccessFlags
gsk_vulkan_image_get_vk_access (GskVulkanImage *self)
{
return self->vk_access;
}
void
gsk_vulkan_image_set_vk_image_layout (GskVulkanImage *self,
VkPipelineStageFlags stage,
VkImageLayout image_layout,
VkAccessFlags access)
{
self->vk_pipeline_stage = stage;
self->vk_image_layout = image_layout;
self->vk_access = access;
}
void
gsk_vulkan_image_transition (GskVulkanImage *self,
VkCommandBuffer command_buffer,
VkPipelineStageFlags stage,
VkImageLayout image_layout,
VkAccessFlags access)
{
if (self->vk_pipeline_stage == stage &&
self->vk_image_layout == image_layout &&
self->vk_access == access)
return;
vkCmdPipelineBarrier (command_buffer,
self->vk_pipeline_stage,
stage,
0,
0, NULL,
0, NULL,
1, &(VkImageMemoryBarrier) {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = self->vk_access,
.dstAccessMask = access,
.oldLayout = self->vk_image_layout,
.newLayout = image_layout,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = self->vk_image,
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1
},
});
gsk_vulkan_image_set_vk_image_layout (self, stage, image_layout, access);
}
VkFormat
gsk_vulkan_image_get_vk_format (GskVulkanImage *self)
{
return self->vk_format;
}
GdkMemoryFormat
gsk_vulkan_image_get_format (GskVulkanImage *self)
{
return self->format;
}

View File

@ -1,80 +0,0 @@
#pragma once
#include <gdk/gdk.h>
#include "gskvulkanbufferprivate.h"
#include "gskvulkancommandpoolprivate.h"
G_BEGIN_DECLS
/* required postprocessing steps before the image van be used */
typedef enum
{
GSK_VULKAN_IMAGE_PREMULTIPLY = (1 << 0),
} GskVulkanImagePostprocess;
#define GSK_TYPE_VULKAN_IMAGE (gsk_vulkan_image_get_type ())
G_DECLARE_FINAL_TYPE (GskVulkanImage, gsk_vulkan_image, GSK, VULKAN_IMAGE, GObject)
GskVulkanImage * gsk_vulkan_image_new_for_swapchain (GdkVulkanContext *context,
VkImage image,
VkFormat format,
gsize width,
gsize height);
GskVulkanImage * gsk_vulkan_image_new_for_atlas (GdkVulkanContext *context,
gsize width,
gsize height);
GskVulkanImage * gsk_vulkan_image_new_for_offscreen (GdkVulkanContext *context,
GdkMemoryFormat preferred_format,
gsize width,
gsize height);
GskVulkanImage * gsk_vulkan_image_new_for_upload (GdkVulkanContext *context,
GdkMemoryFormat format,
gsize width,
gsize height);
guchar * gsk_vulkan_image_try_map (GskVulkanImage *self,
gsize *out_stride);
void gsk_vulkan_image_unmap (GskVulkanImage *self);
gsize gsk_vulkan_image_get_width (GskVulkanImage *self);
gsize gsk_vulkan_image_get_height (GskVulkanImage *self);
GskVulkanImagePostprocess
gsk_vulkan_image_get_postprocess (GskVulkanImage *self);
VkPipelineStageFlags gsk_vulkan_image_get_vk_pipeline_stage (GskVulkanImage *self);
VkImageLayout gsk_vulkan_image_get_vk_image_layout (GskVulkanImage *self);
VkAccessFlags gsk_vulkan_image_get_vk_access (GskVulkanImage *self);
void gsk_vulkan_image_set_vk_image_layout (GskVulkanImage *self,
VkPipelineStageFlags stage,
VkImageLayout image_layout,
VkAccessFlags access);
void gsk_vulkan_image_transition (GskVulkanImage *self,
VkCommandBuffer command_buffer,
VkPipelineStageFlags stage,
VkImageLayout image_layout,
VkAccessFlags access);
#define gdk_vulkan_image_transition_shader(image) \
gsk_vulkan_image_transition ((image), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, \
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_SHADER_READ_BIT)
VkImage gsk_vulkan_image_get_vk_image (GskVulkanImage *self);
VkImageView gsk_vulkan_image_get_image_view (GskVulkanImage *self);
VkFormat gsk_vulkan_image_get_vk_format (GskVulkanImage *self);
GdkMemoryFormat gsk_vulkan_image_get_format (GskVulkanImage *self);
VkFramebuffer gsk_vulkan_image_get_framebuffer (GskVulkanImage *self,
VkRenderPass pass);
static inline void
print_image (GString *string,
GskVulkanImage *image)
{
g_string_append_printf (string, "%zux%zu ",
gsk_vulkan_image_get_width (image),
gsk_vulkan_image_get_height (image));
}
G_END_DECLS

View File

@ -1,101 +0,0 @@
#include "config.h"
#include "gskvulkaninsetshadowopprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanshaderopprivate.h"
#include "gsk/gskroundedrectprivate.h"
#include "vulkan/resources/inset-shadow.vert.h"
typedef struct _GskVulkanInsetShadowOp GskVulkanInsetShadowOp;
struct _GskVulkanInsetShadowOp
{
GskVulkanShaderOp op;
GskRoundedRect outline;
GdkRGBA color;
graphene_point_t offset;
float spread;
float blur_radius;
};
static void
gsk_vulkan_inset_shadow_op_finish (GskVulkanOp *op)
{
}
static void
gsk_vulkan_inset_shadow_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanInsetShadowOp *self = (GskVulkanInsetShadowOp *) op;
print_indent (string, indent);
print_rounded_rect (string, &self->outline);
g_string_append (string, "inset-shadow ");
if (self->blur_radius > 0)
g_string_append_printf (string, "blur %gpx ", self->blur_radius);
print_newline (string);
}
static void
gsk_vulkan_inset_shadow_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
GskVulkanInsetShadowOp *self = (GskVulkanInsetShadowOp *) op;
GskVulkanInsetShadowInstance *instance = (GskVulkanInsetShadowInstance *) (data + ((GskVulkanShaderOp *) op)->vertex_offset);
gsk_rounded_rect_to_float (&self->outline, graphene_point_zero (), instance->outline);
gsk_vulkan_rgba_to_float (&self->color, instance->color);
gsk_vulkan_point_to_float (&self->offset, instance->offset);
instance->spread = self->spread;
instance->blur_radius = self->blur_radius;
}
static void
gsk_vulkan_inset_shadow_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
}
static const GskVulkanShaderOpClass GSK_VULKAN_INSET_SHADOW_OP_CLASS = {
{
GSK_VULKAN_OP_SIZE (GskVulkanInsetShadowOp),
GSK_VULKAN_STAGE_SHADER,
gsk_vulkan_inset_shadow_op_finish,
gsk_vulkan_inset_shadow_op_print,
gsk_vulkan_shader_op_count_vertex_data,
gsk_vulkan_inset_shadow_op_collect_vertex_data,
gsk_vulkan_inset_shadow_op_reserve_descriptor_sets,
gsk_vulkan_shader_op_command
},
"inset-shadow",
0,
&gsk_vulkan_inset_shadow_info,
};
void
gsk_vulkan_inset_shadow_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const GskRoundedRect *outline,
const graphene_point_t *offset,
const GdkRGBA *color,
const graphene_point_t *shadow_offset,
float spread,
float blur_radius)
{
GskVulkanInsetShadowOp *self;
self = (GskVulkanInsetShadowOp *) gsk_vulkan_shader_op_alloc (render, &GSK_VULKAN_INSET_SHADOW_OP_CLASS, clip, NULL);
self->outline = *outline;
gsk_rounded_rect_offset (&self->outline, offset->x, offset->y);
self->color = *color;
self->offset = *shadow_offset;
self->spread = spread;
self->blur_radius = blur_radius;
}

View File

@ -1,18 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_inset_shadow_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const GskRoundedRect *outline,
const graphene_point_t *offset,
const GdkRGBA *color,
const graphene_point_t *shadow_offset,
float spread,
float blur_radius);
G_END_DECLS

View File

@ -1,113 +0,0 @@
#include "config.h"
#include "gskvulkanlineargradientopprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanshaderopprivate.h"
#include "vulkan/resources/linear.vert.h"
typedef struct _GskVulkanLinearGradientOp GskVulkanLinearGradientOp;
struct _GskVulkanLinearGradientOp
{
GskVulkanShaderOp op;
graphene_rect_t rect;
graphene_point_t start;
graphene_point_t end;
gboolean repeating;
GskColorStop *stops;
gsize n_stops;
gsize buffer_offset;
};
static void
gsk_vulkan_linear_gradient_op_finish (GskVulkanOp *op)
{
GskVulkanLinearGradientOp *self = (GskVulkanLinearGradientOp *) op;
g_free (self->stops);
}
static void
gsk_vulkan_linear_gradient_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanLinearGradientOp *self = (GskVulkanLinearGradientOp *) op;
print_indent (string, indent);
print_rect (string, &self->rect);
g_string_append_printf (string, "linear-gradient (%zu stops)", self->n_stops);
print_newline (string);
}
static void
gsk_vulkan_linear_gradient_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
GskVulkanLinearGradientOp *self = (GskVulkanLinearGradientOp *) op;
GskVulkanLinearInstance *instance = (GskVulkanLinearInstance *) (data + ((GskVulkanShaderOp *) op)->vertex_offset);
gsk_rect_to_float (&self->rect, instance->rect);
gsk_vulkan_point_to_float (&self->start, instance->start);
gsk_vulkan_point_to_float (&self->end, instance->end);
instance->repeating = self->repeating;
instance->stop_offset = self->buffer_offset;
instance->stop_count = self->n_stops;
}
static void
gsk_vulkan_linear_gradient_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
GskVulkanLinearGradientOp *self = (GskVulkanLinearGradientOp *) op;
guchar *mem;
mem = gsk_vulkan_render_get_buffer_memory (render,
self->n_stops * sizeof (GskColorStop),
G_ALIGNOF (GskColorStop),
&self->buffer_offset);
memcpy (mem, self->stops, self->n_stops * sizeof (GskColorStop));
}
static const GskVulkanShaderOpClass GSK_VULKAN_LINEAR_GRADIENT_OP_CLASS = {
{
GSK_VULKAN_OP_SIZE (GskVulkanLinearGradientOp),
GSK_VULKAN_STAGE_SHADER,
gsk_vulkan_linear_gradient_op_finish,
gsk_vulkan_linear_gradient_op_print,
gsk_vulkan_shader_op_count_vertex_data,
gsk_vulkan_linear_gradient_op_collect_vertex_data,
gsk_vulkan_linear_gradient_op_reserve_descriptor_sets,
gsk_vulkan_shader_op_command
},
"linear",
0,
&gsk_vulkan_linear_info,
};
void
gsk_vulkan_linear_gradient_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_point_t *start,
const graphene_point_t *end,
gboolean repeating,
const GskColorStop *stops,
gsize n_stops)
{
GskVulkanLinearGradientOp *self;
self = (GskVulkanLinearGradientOp *) gsk_vulkan_shader_op_alloc (render, &GSK_VULKAN_LINEAR_GRADIENT_OP_CLASS, clip, NULL);
graphene_rect_offset_r (rect, offset->x, offset->y, &self->rect);
self->start = GRAPHENE_POINT_INIT (start->x + offset->x, start->y + offset->y);
self->end = GRAPHENE_POINT_INIT (end->x + offset->x, end->y + offset->y);
self->repeating = repeating;
self->stops = g_memdup (stops, sizeof (GskColorStop) * n_stops);
self->n_stops = n_stops;
}

View File

@ -1,19 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_linear_gradient_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_point_t *start,
const graphene_point_t *end,
gboolean repeating,
const GskColorStop *stops,
gsize n_stops);
G_END_DECLS

View File

@ -1,126 +0,0 @@
#include "config.h"
#include "gskvulkanmaskopprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanshaderopprivate.h"
#include "vulkan/resources/mask.vert.h"
typedef struct _GskVulkanMaskOp GskVulkanMaskOp;
struct _GskVulkanMaskOp
{
GskVulkanShaderOp op;
struct {
graphene_rect_t rect;
graphene_rect_t tex_rect;
guint32 image_descriptor;
} source, mask;
GskMaskMode mask_mode;
};
static void
gsk_vulkan_mask_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanMaskOp *self = (GskVulkanMaskOp *) op;
print_indent (string, indent);
print_rect (string, &self->source.rect);
g_string_append (string, "mask ");
print_rect (string, &self->mask.rect);
switch (self->mask_mode)
{
case GSK_MASK_MODE_ALPHA:
g_string_append (string, "alpha ");
break;
case GSK_MASK_MODE_INVERTED_ALPHA:
g_string_append (string, "inverted-alpha ");
break;
case GSK_MASK_MODE_LUMINANCE:
g_string_append (string, "luminance ");
break;
case GSK_MASK_MODE_INVERTED_LUMINANCE:
g_string_append (string, "inverted-luminance ");
break;
default:
g_assert_not_reached ();
break;
}
print_newline (string);
}
static void
gsk_vulkan_mask_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
GskVulkanMaskOp *self = (GskVulkanMaskOp *) op;
GskVulkanMaskInstance *instance = (GskVulkanMaskInstance *) (data + ((GskVulkanShaderOp *) op)->vertex_offset);
gsk_rect_to_float (&self->source.rect, instance->source_rect);
gsk_rect_to_float (&self->source.tex_rect, instance->source_tex_rect);
instance->source_id = self->source.image_descriptor;
gsk_rect_to_float (&self->mask.rect, instance->mask_rect);
gsk_rect_to_float (&self->mask.tex_rect, instance->mask_tex_rect);
instance->mask_id = self->mask.image_descriptor;
instance->mask_mode = self->mask_mode;
}
static void
gsk_vulkan_mask_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
GskVulkanMaskOp *self = (GskVulkanMaskOp *) op;
GskVulkanShaderOp *shader = (GskVulkanShaderOp *) op;
self->source.image_descriptor = gsk_vulkan_render_get_image_descriptor (render, shader->images[0], GSK_VULKAN_SAMPLER_DEFAULT);
self->mask.image_descriptor = gsk_vulkan_render_get_image_descriptor (render, shader->images[1], GSK_VULKAN_SAMPLER_DEFAULT);
}
static const GskVulkanShaderOpClass GSK_VULKAN_COLOR_MASK_OP_CLASS = {
{
GSK_VULKAN_OP_SIZE (GskVulkanMaskOp),
GSK_VULKAN_STAGE_SHADER,
gsk_vulkan_shader_op_finish,
gsk_vulkan_mask_op_print,
gsk_vulkan_shader_op_count_vertex_data,
gsk_vulkan_mask_op_collect_vertex_data,
gsk_vulkan_mask_op_reserve_descriptor_sets,
gsk_vulkan_shader_op_command
},
"mask",
2,
&gsk_vulkan_mask_info,
};
void
gsk_vulkan_mask_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const graphene_point_t *offset,
GskVulkanImage *source,
const graphene_rect_t *source_rect,
const graphene_rect_t *source_tex_rect,
GskVulkanImage *mask,
const graphene_rect_t *mask_rect,
const graphene_rect_t *mask_tex_rect,
GskMaskMode mask_mode)
{
GskVulkanMaskOp *self;
self = (GskVulkanMaskOp *) gsk_vulkan_shader_op_alloc (render,
&GSK_VULKAN_COLOR_MASK_OP_CLASS,
clip,
(GskVulkanImage *[2]) {
source,
mask,
});
graphene_rect_offset_r (source_rect, offset->x, offset->y, &self->source.rect);
gsk_vulkan_normalize_tex_coords (&self->source.tex_rect, source_rect, source_tex_rect);
graphene_rect_offset_r (mask_rect, offset->x, offset->y, &self->mask.rect);
gsk_vulkan_normalize_tex_coords (&self->mask.tex_rect, mask_rect, mask_tex_rect);
self->mask_mode = mask_mode;
}

View File

@ -1,20 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_mask_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const graphene_point_t *offset,
GskVulkanImage *source,
const graphene_rect_t *source_rect,
const graphene_rect_t *source_tex_rect,
GskVulkanImage *mask,
const graphene_rect_t *mask_rect,
const graphene_rect_t *mask_tex_rect,
GskMaskMode mask_mode);
G_END_DECLS

View File

@ -1,120 +0,0 @@
#include "config.h"
#include "gskvulkanmemoryprivate.h"
#include "gskvulkanprivate.h"
struct _GskVulkanMemory
{
GdkVulkanContext *vulkan;
gsize size;
VkMemoryType vk_memory_type;
VkDeviceMemory vk_memory;
};
GskVulkanMemory *
gsk_vulkan_memory_new (GdkVulkanContext *context,
uint32_t allowed_types,
VkMemoryPropertyFlags flags,
gsize size)
{
VkPhysicalDeviceMemoryProperties properties;
GskVulkanMemory *self;
uint32_t i;
self = g_new0 (GskVulkanMemory, 1);
self->vulkan = g_object_ref (context);
self->size = size;
vkGetPhysicalDeviceMemoryProperties (gdk_vulkan_context_get_physical_device (context),
&properties);
for (i = 0; i < properties.memoryTypeCount; i++)
{
if (!(allowed_types & (1 << i)))
continue;
if ((properties.memoryTypes[i].propertyFlags & flags) == flags)
break;
}
g_assert (i < properties.memoryTypeCount);
self->vk_memory_type = properties.memoryTypes[i];
GSK_VK_CHECK (vkAllocateMemory, gdk_vulkan_context_get_device (context),
&(VkMemoryAllocateInfo) {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = size,
.memoryTypeIndex = i
},
NULL,
&self->vk_memory);
return self;
}
void
gsk_vulkan_memory_free (GskVulkanMemory *self)
{
vkFreeMemory (gdk_vulkan_context_get_device (self->vulkan),
self->vk_memory,
NULL);
g_object_unref (self->vulkan);
g_free (self);
}
VkDeviceMemory
gsk_vulkan_memory_get_device_memory (GskVulkanMemory *self)
{
return self->vk_memory;
}
gboolean
gsk_vulkan_memory_can_map (GskVulkanMemory *self,
gboolean fast)
{
if (!(self->vk_memory_type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
return FALSE;
/* FIXME: no support implemented for this */
if (!(self->vk_memory_type.propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
return FALSE;
if (!fast)
return TRUE;
if (!(self->vk_memory_type.propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT))
return FALSE;
return TRUE;
}
guchar *
gsk_vulkan_memory_map (GskVulkanMemory *self)
{
void *data;
g_assert (gsk_vulkan_memory_can_map (self, FALSE));
GSK_VK_CHECK (vkMapMemory, gdk_vulkan_context_get_device (self->vulkan),
self->vk_memory,
0,
self->size,
0,
&data);
return data;
}
void
gsk_vulkan_memory_unmap (GskVulkanMemory *self)
{
vkUnmapMemory (gdk_vulkan_context_get_device (self->vulkan),
self->vk_memory);
}

View File

@ -1,23 +0,0 @@
#pragma once
#include <gdk/gdk.h>
G_BEGIN_DECLS
typedef struct _GskVulkanMemory GskVulkanMemory;
GskVulkanMemory * gsk_vulkan_memory_new (GdkVulkanContext *context,
uint32_t allowed_types,
VkMemoryPropertyFlags properties,
gsize size);
void gsk_vulkan_memory_free (GskVulkanMemory *memory);
VkDeviceMemory gsk_vulkan_memory_get_device_memory (GskVulkanMemory *self);
gboolean gsk_vulkan_memory_can_map (GskVulkanMemory *self,
gboolean fast);
guchar * gsk_vulkan_memory_map (GskVulkanMemory *self);
void gsk_vulkan_memory_unmap (GskVulkanMemory *self);
G_END_DECLS

View File

@ -1,60 +0,0 @@
#include "config.h"
#include "gskvulkanopprivate.h"
GskVulkanOp *
gsk_vulkan_op_alloc (GskVulkanRender *render,
const GskVulkanOpClass *op_class)
{
GskVulkanOp *op;
op = gsk_vulkan_render_alloc_op (render, op_class->size);
op->op_class = op_class;
return op;
}
void
gsk_vulkan_op_finish (GskVulkanOp *op)
{
op->op_class->finish (op);
}
void
gsk_vulkan_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
op->op_class->print (op, string, indent);
}
gsize
gsk_vulkan_op_count_vertex_data (GskVulkanOp *op,
gsize n_bytes)
{
return op->op_class->count_vertex_data (op, n_bytes);
}
void
gsk_vulkan_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
op->op_class->collect_vertex_data (op, data);
}
void
gsk_vulkan_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
op->op_class->reserve_descriptor_sets (op, render);
}
GskVulkanOp *
gsk_vulkan_op_command (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer)
{
return op->op_class->command (op, render, render_pass, command_buffer);
}

View File

@ -1,72 +0,0 @@
#pragma once
#include <gdk/gdk.h>
#include "gskvulkanrenderpassprivate.h"
G_BEGIN_DECLS
typedef enum
{
GSK_VULKAN_STAGE_UPLOAD,
GSK_VULKAN_STAGE_COMMAND,
GSK_VULKAN_STAGE_SHADER,
/* magic ones */
GSK_VULKAN_STAGE_BEGIN_PASS,
GSK_VULKAN_STAGE_END_PASS
} GskVulkanStage;
struct _GskVulkanOp
{
const GskVulkanOpClass *op_class;
GskVulkanOp *next;
};
struct _GskVulkanOpClass
{
gsize size;
GskVulkanStage stage;
void (* finish) (GskVulkanOp *op);
void (* print) (GskVulkanOp *op,
GString *string,
guint indent);
gsize (* count_vertex_data) (GskVulkanOp *op,
gsize n_bytes);
void (* collect_vertex_data) (GskVulkanOp *op,
guchar *data);
void (* reserve_descriptor_sets) (GskVulkanOp *op,
GskVulkanRender *render);
GskVulkanOp * (* command) (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer);
};
/* ensures alignment of ops to multipes of 16 bytes - and that makes graphene happy */
#define GSK_VULKAN_OP_SIZE(struct_name) ((sizeof(struct_name) + 15) & ~15)
GskVulkanOp * gsk_vulkan_op_alloc (GskVulkanRender *render,
const GskVulkanOpClass *op_class);
void gsk_vulkan_op_finish (GskVulkanOp *op);
void gsk_vulkan_op_print (GskVulkanOp *op,
GString *string,
guint indent);
gsize gsk_vulkan_op_count_vertex_data (GskVulkanOp *op,
gsize n_bytes);
void gsk_vulkan_op_collect_vertex_data (GskVulkanOp *op,
guchar *data);
void gsk_vulkan_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render);
GskVulkanOp * gsk_vulkan_op_command (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer);
G_END_DECLS

View File

@ -1,101 +0,0 @@
#include "config.h"
#include "gskvulkanoutsetshadowopprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanshaderopprivate.h"
#include "gsk/gskroundedrectprivate.h"
#include "vulkan/resources/outset-shadow.vert.h"
typedef struct _GskVulkanOutsetShadowOp GskVulkanOutsetShadowOp;
struct _GskVulkanOutsetShadowOp
{
GskVulkanShaderOp op;
GskRoundedRect outline;
GdkRGBA color;
graphene_point_t offset;
float spread;
float blur_radius;
};
static void
gsk_vulkan_outset_shadow_op_finish (GskVulkanOp *op)
{
}
static void
gsk_vulkan_outset_shadow_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanOutsetShadowOp *self = (GskVulkanOutsetShadowOp *) op;
print_indent (string, indent);
print_rounded_rect (string, &self->outline);
g_string_append (string, "outset-shadow ");
if (self->blur_radius > 0)
g_string_append_printf (string, "blur %gpx ", self->blur_radius);
print_newline (string);
}
static void
gsk_vulkan_outset_shadow_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
GskVulkanOutsetShadowOp *self = (GskVulkanOutsetShadowOp *) op;
GskVulkanOutsetShadowInstance *instance = (GskVulkanOutsetShadowInstance *) (data + ((GskVulkanShaderOp *) op)->vertex_offset);
gsk_rounded_rect_to_float (&self->outline, graphene_point_zero (), instance->outline);
gsk_vulkan_rgba_to_float (&self->color, instance->color);
gsk_vulkan_point_to_float (&self->offset, instance->offset);
instance->spread = self->spread;
instance->blur_radius = self->blur_radius;
}
static void
gsk_vulkan_outset_shadow_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
}
static const GskVulkanShaderOpClass GSK_VULKAN_OUTSET_SHADOW_OP_CLASS = {
{
GSK_VULKAN_OP_SIZE (GskVulkanOutsetShadowOp),
GSK_VULKAN_STAGE_SHADER,
gsk_vulkan_outset_shadow_op_finish,
gsk_vulkan_outset_shadow_op_print,
gsk_vulkan_shader_op_count_vertex_data,
gsk_vulkan_outset_shadow_op_collect_vertex_data,
gsk_vulkan_outset_shadow_op_reserve_descriptor_sets,
gsk_vulkan_shader_op_command
},
"outset-shadow",
0,
&gsk_vulkan_outset_shadow_info,
};
void
gsk_vulkan_outset_shadow_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const GskRoundedRect *outline,
const graphene_point_t *offset,
const GdkRGBA *color,
const graphene_point_t *shadow_offset,
float spread,
float blur_radius)
{
GskVulkanOutsetShadowOp *self;
self = (GskVulkanOutsetShadowOp *) gsk_vulkan_shader_op_alloc (render, &GSK_VULKAN_OUTSET_SHADOW_OP_CLASS, clip, NULL);
self->outline = *outline;
gsk_rounded_rect_offset (&self->outline, offset->x, offset->y);
self->color = *color;
self->offset = *shadow_offset;
self->spread = spread;
self->blur_radius = blur_radius;
}

View File

@ -1,18 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_outset_shadow_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
const GskRoundedRect *outline,
const graphene_point_t *offset,
const GdkRGBA *color,
const graphene_point_t *shadow_offset,
float spread,
float blur_radius);
G_END_DECLS

View File

@ -1,133 +0,0 @@
#pragma once
#include "gskdebugprivate.h"
#include "gskrectprivate.h"
#include "gskroundedrectprivate.h"
#include <gdk/gdk.h>
#include <graphene.h>
typedef struct _GskVulkanOp GskVulkanOp;
typedef struct _GskVulkanOpClass GskVulkanOpClass;
typedef struct _GskVulkanRender GskVulkanRender;
typedef struct _GskVulkanRenderPass GskVulkanRenderPass;
static inline VkResult
gsk_vulkan_handle_result (VkResult res,
const char *called_function)
{
if (res != VK_SUCCESS)
{
GSK_DEBUG (VULKAN, "%s(): %s (%d)", called_function, gdk_vulkan_strerror (res), res);
}
return res;
}
#define GSK_VK_CHECK(func, ...) gsk_vulkan_handle_result (func (__VA_ARGS__), G_STRINGIFY (func))
static inline void
gsk_vulkan_normalize_tex_coords (graphene_rect_t *tex_coords,
const graphene_rect_t *rect,
const graphene_rect_t *tex)
{
graphene_rect_init (tex_coords,
(rect->origin.x - tex->origin.x) / tex->size.width,
(rect->origin.y - tex->origin.y) / tex->size.height,
rect->size.width / tex->size.width,
rect->size.height / tex->size.height);
}
static inline void
gsk_vulkan_rgba_to_float (const GdkRGBA *rgba,
float values[4])
{
values[0] = rgba->red;
values[1] = rgba->green;
values[2] = rgba->blue;
values[3] = rgba->alpha;
}
static inline void
gsk_vulkan_point_to_float (const graphene_point_t *point,
float values[2])
{
values[0] = point->x;
values[1] = point->y;
}
static inline void
print_indent (GString *string,
guint indent)
{
g_string_append_printf (string, "%*s", 2 * indent, "");
}
static inline void
print_rect (GString *string,
const graphene_rect_t *rect)
{
g_string_append_printf (string, "%g %g %g %g ",
rect->origin.x, rect->origin.y,
rect->size.width, rect->size.height);
}
static inline void
print_int_rect (GString *string,
const cairo_rectangle_int_t *rect)
{
g_string_append_printf (string, "%d %d %d %d ",
rect->x, rect->y,
rect->width, rect->height);
}
static inline void
print_rounded_rect (GString *string,
const GskRoundedRect *rect)
{
print_rect (string, &rect->bounds);
if (gsk_rounded_rect_is_rectilinear (rect))
return;
g_string_append (string, "/ ");
if (rect->corner[0].width != rect->corner[0].height ||
rect->corner[1].width != rect->corner[1].height ||
rect->corner[2].width != rect->corner[2].height ||
rect->corner[3].width != rect->corner[3].height)
{
g_string_append (string, "variable ");
}
else if (rect->corner[0].width != rect->corner[1].width ||
rect->corner[0].width != rect->corner[2].width ||
rect->corner[0].width != rect->corner[3].width)
{
g_string_append_printf (string, "%g %g %g %g ",
rect->corner[0].width, rect->corner[1].width,
rect->corner[2].width, rect->corner[3].width);
}
else
{
g_string_append_printf (string, "%g ", rect->corner[0].width);
}
}
static inline void
print_rgba (GString *string,
const GdkRGBA *rgba)
{
char *s = gdk_rgba_to_string (rgba);
g_string_append (string, s);
g_string_append_c (string, ' ');
g_free (s);
}
static inline void
print_newline (GString *string)
{
if (string->len && string->str[string->len - 1] == ' ')
string->str[string->len - 1] = '\n';
else
g_string_append_c (string, '\n');
}

View File

@ -1,121 +0,0 @@
#include "config.h"
#include "gskvulkanpushconstantsopprivate.h"
#include "gskroundedrectprivate.h"
#include "gskvulkanprivate.h"
typedef struct _GskVulkanPushConstantsOp GskVulkanPushConstantsOp;
typedef struct _GskVulkanPushConstantsInstance GskVulkanPushConstantsInstance;
struct _GskVulkanPushConstantsInstance
{
float mvp[16];
float clip[12];
float scale[2];
};
struct _GskVulkanPushConstantsOp
{
GskVulkanOp op;
GskVulkanPushConstantsInstance instance;
};
uint32_t
gsk_vulkan_push_constants_get_range_count (void)
{
return 1;
}
const VkPushConstantRange *
gsk_vulkan_push_constants_get_ranges (void)
{
static const VkPushConstantRange ranges[1] = {
{
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
.offset = 0,
.size = sizeof (GskVulkanPushConstantsInstance)
}
};
return ranges;
}
static void
gsk_vulkan_push_constants_op_finish (GskVulkanOp *op)
{
}
static void
gsk_vulkan_push_constants_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
print_indent (string, indent);
g_string_append_printf (string, "push-constants ");
print_newline (string);
}
static gsize
gsk_vulkan_push_constants_op_count_vertex_data (GskVulkanOp *op,
gsize n_bytes)
{
return n_bytes;
}
static void
gsk_vulkan_push_constants_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
}
static void
gsk_vulkan_push_constants_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
}
static GskVulkanOp *
gsk_vulkan_push_constants_op_command (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer)
{
GskVulkanPushConstantsOp *self = (GskVulkanPushConstantsOp *) op;
vkCmdPushConstants (command_buffer,
gsk_vulkan_render_get_pipeline_layout (render),
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
0,
sizeof (self->instance),
&self->instance);
return op->next;
}
static const GskVulkanOpClass GSK_VULKAN_PUSH_CONSTANTS_OP_CLASS = {
GSK_VULKAN_OP_SIZE (GskVulkanPushConstantsOp),
GSK_VULKAN_STAGE_COMMAND,
gsk_vulkan_push_constants_op_finish,
gsk_vulkan_push_constants_op_print,
gsk_vulkan_push_constants_op_count_vertex_data,
gsk_vulkan_push_constants_op_collect_vertex_data,
gsk_vulkan_push_constants_op_reserve_descriptor_sets,
gsk_vulkan_push_constants_op_command
};
void
gsk_vulkan_push_constants_op (GskVulkanRender *render,
const graphene_vec2_t *scale,
const graphene_matrix_t *mvp,
const GskRoundedRect *clip)
{
GskVulkanPushConstantsOp *self;
self = (GskVulkanPushConstantsOp *) gsk_vulkan_op_alloc (render, &GSK_VULKAN_PUSH_CONSTANTS_OP_CLASS);
graphene_matrix_to_float (mvp, self->instance.mvp);
gsk_rounded_rect_to_float (clip, graphene_point_zero (), self->instance.clip);
graphene_vec2_to_float (scale, self->instance.scale);
}

View File

@ -1,18 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
const VkPushConstantRange *
gsk_vulkan_push_constants_get_ranges (void) G_GNUC_PURE;
uint32_t gsk_vulkan_push_constants_get_range_count (void) G_GNUC_PURE;
void gsk_vulkan_push_constants_op (GskVulkanRender *render,
const graphene_vec2_t *scale,
const graphene_matrix_t *mvp,
const GskRoundedRect *clip);
G_END_DECLS

File diff suppressed because it is too large Load Diff

View File

@ -1,517 +0,0 @@
#include "config.h"
#include "gskvulkanrendererprivate.h"
#include "gskdebugprivate.h"
#include "gskprivate.h"
#include "gskrendererprivate.h"
#include "gskrendernodeprivate.h"
#include "gskvulkanbufferprivate.h"
#include "gskvulkanimageprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanrenderprivate.h"
#include "gskvulkanglyphcacheprivate.h"
#include "gdk/gdkdisplayprivate.h"
#include "gdk/gdkdrawcontextprivate.h"
#include "gdk/gdkprofilerprivate.h"
#include "gdk/gdktextureprivate.h"
#include "gdk/gdkvulkancontextprivate.h"
#include <graphene.h>
#define GSK_VULKAN_MAX_RENDERS 4
typedef struct _GskVulkanTextureData GskVulkanTextureData;
struct _GskVulkanTextureData {
GdkTexture *texture;
GskVulkanImage *image;
GskVulkanRenderer *renderer;
};
#ifdef G_ENABLE_DEBUG
typedef struct {
GQuark frames;
GQuark render_passes;
GQuark fallback_pixels;
GQuark texture_pixels;
} ProfileCounters;
typedef struct {
GQuark cpu_time;
GQuark gpu_time;
} ProfileTimers;
static guint texture_pixels_counter;
static guint fallback_pixels_counter;
#endif
struct _GskVulkanRenderer
{
GskRenderer parent_instance;
GdkVulkanContext *vulkan;
guint n_targets;
GskVulkanImage **targets;
GskVulkanRender *renders[GSK_VULKAN_MAX_RENDERS];
GSList *textures;
GskVulkanGlyphCache *glyph_cache;
#ifdef G_ENABLE_DEBUG
ProfileCounters profile_counters;
ProfileTimers profile_timers;
#endif
};
struct _GskVulkanRendererClass
{
GskRendererClass parent_class;
};
G_DEFINE_TYPE (GskVulkanRenderer, gsk_vulkan_renderer, GSK_TYPE_RENDERER)
static cairo_region_t *
get_render_region (GskVulkanRenderer *self)
{
const cairo_region_t *damage;
cairo_region_t *render_region;
cairo_region_t *scaled_damage;
GdkRectangle whole_surface;
GdkRectangle extents;
GdkSurface *surface;
double scale;
render_region = NULL;
surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self->vulkan));
scale = gdk_surface_get_scale (surface);
whole_surface.x = 0;
whole_surface.y = 0;
whole_surface.width = gdk_surface_get_width (surface);
whole_surface.height = gdk_surface_get_height (surface);
damage = gdk_draw_context_get_frame_region (GDK_DRAW_CONTEXT (self->vulkan));
scaled_damage = cairo_region_create ();
for (int i = 0; i < cairo_region_num_rectangles (damage); i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (damage, i, &rect);
cairo_region_union_rectangle (scaled_damage, &(cairo_rectangle_int_t) {
.x = (int) floor (rect.x * scale),
.y = (int) floor (rect.y * scale),
.width = (int) ceil ((rect.x + rect.width) * scale) - floor (rect.x * scale),
.height = (int) ceil ((rect.y + rect.height) * scale) - floor (rect.y * scale),
});
}
if (cairo_region_contains_rectangle (scaled_damage, &whole_surface) == CAIRO_REGION_OVERLAP_IN)
goto out;
cairo_region_get_extents (scaled_damage, &extents);
if (gdk_rectangle_equal (&extents, &whole_surface))
goto out;
render_region = cairo_region_create_rectangle (&extents);
out:
g_clear_pointer (&scaled_damage, cairo_region_destroy);
return g_steal_pointer (&render_region);
}
static void
gsk_vulkan_renderer_free_targets (GskVulkanRenderer *self)
{
guint i;
for (i = 0; i < self->n_targets; i++)
{
g_object_unref (self->targets[i]);
}
g_clear_pointer (&self->targets, g_free);
self->n_targets = 0;
}
static void
gsk_vulkan_renderer_update_images_cb (GdkVulkanContext *context,
GskVulkanRenderer *self)
{
GdkSurface *surface;
double scale;
gsize width, height;
guint i;
surface = gsk_renderer_get_surface (GSK_RENDERER (self));
if (surface == NULL)
return;
gsk_vulkan_renderer_free_targets (self);
self->n_targets = gdk_vulkan_context_get_n_images (context);
self->targets = g_new (GskVulkanImage *, self->n_targets);
scale = gdk_surface_get_scale (surface);
width = (int) ceil (gdk_surface_get_width (surface) * scale);
height = (int) ceil (gdk_surface_get_height (surface) * scale);
for (i = 0; i < self->n_targets; i++)
{
self->targets[i] = gsk_vulkan_image_new_for_swapchain (self->vulkan,
gdk_vulkan_context_get_image (context, i),
gdk_vulkan_context_get_image_format (self->vulkan),
width, height);
}
}
static GskVulkanRender *
gsk_vulkan_renderer_get_render (GskVulkanRenderer *self)
{
VkFence fences[G_N_ELEMENTS (self->renders)];
VkDevice device;
guint i;
device = gdk_vulkan_context_get_device (self->vulkan);
while (TRUE)
{
for (i = 0; i < G_N_ELEMENTS (self->renders); i++)
{
if (self->renders[i] == NULL)
{
self->renders[i] = gsk_vulkan_render_new (GSK_RENDERER (self), self->vulkan);
return self->renders[i];
}
fences[i] = gsk_vulkan_render_get_fence (self->renders[i]);
if (vkGetFenceStatus (device, fences[i]) == VK_SUCCESS)
return self->renders[i];
}
GSK_VK_CHECK (vkWaitForFences, device,
G_N_ELEMENTS (fences),
fences,
VK_FALSE,
INT64_MAX);
}
}
static gboolean
gsk_vulkan_renderer_realize (GskRenderer *renderer,
GdkSurface *surface,
GError **error)
{
GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
if (surface == NULL)
self->vulkan = gdk_display_create_vulkan_context (gdk_display_get_default (), error);
else
self->vulkan = gdk_surface_create_vulkan_context (surface, error);
if (self->vulkan == NULL)
return FALSE;
g_signal_connect (self->vulkan,
"images-updated",
G_CALLBACK (gsk_vulkan_renderer_update_images_cb),
self);
gsk_vulkan_renderer_update_images_cb (self->vulkan, self);
self->glyph_cache = gsk_vulkan_glyph_cache_new (self->vulkan);
return TRUE;
}
static void
gsk_vulkan_renderer_unrealize (GskRenderer *renderer)
{
GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
GSList *l;
guint i;
g_clear_object (&self->glyph_cache);
for (l = self->textures; l; l = l->next)
{
GskVulkanTextureData *data = l->data;
data->renderer = NULL;
gdk_texture_clear_render_data (data->texture);
}
g_clear_pointer (&self->textures, g_slist_free);
for (i = 0; i < G_N_ELEMENTS (self->renders); i++)
g_clear_pointer (&self->renders[i], gsk_vulkan_render_free);
gsk_vulkan_renderer_free_targets (self);
g_signal_handlers_disconnect_by_func(self->vulkan,
gsk_vulkan_renderer_update_images_cb,
self);
g_clear_object (&self->vulkan);
}
static void
gsk_vulkan_renderer_download_texture_cb (gpointer user_data,
GdkMemoryFormat format,
const guchar *data,
int width,
int height,
gsize stride)
{
GdkTexture **texture = (GdkTexture **) user_data;
GBytes *bytes;
bytes = g_bytes_new (data, stride * height);
*texture = gdk_memory_texture_new (width, height,
format,
bytes,
stride);
g_bytes_unref (bytes);
}
static GdkTexture *
gsk_vulkan_renderer_render_texture (GskRenderer *renderer,
GskRenderNode *root,
const graphene_rect_t *viewport)
{
GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
GskVulkanRender *render;
GskVulkanImage *image;
GdkTexture *texture;
graphene_rect_t rounded_viewport;
#ifdef G_ENABLE_DEBUG
GskProfiler *profiler;
gint64 cpu_time;
gint64 start_time G_GNUC_UNUSED;
#endif
#ifdef G_ENABLE_DEBUG
profiler = gsk_renderer_get_profiler (renderer);
gsk_profiler_counter_set (profiler, self->profile_counters.fallback_pixels, 0);
gsk_profiler_counter_set (profiler, self->profile_counters.texture_pixels, 0);
gsk_profiler_counter_set (profiler, self->profile_counters.render_passes, 0);
gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
#endif
render = gsk_vulkan_render_new (renderer, self->vulkan);
rounded_viewport = GRAPHENE_RECT_INIT (viewport->origin.x,
viewport->origin.y,
ceil (viewport->size.width),
ceil (viewport->size.height));
image = gsk_vulkan_image_new_for_offscreen (self->vulkan,
gdk_vulkan_context_get_offscreen_format (self->vulkan,
gsk_render_node_get_preferred_depth (root)),
rounded_viewport.size.width,
rounded_viewport.size.height);
texture = NULL;
gsk_vulkan_render_render (render,
image,
&rounded_viewport,
NULL,
root,
gsk_vulkan_renderer_download_texture_cb,
&texture);
gsk_vulkan_render_free (render);
g_object_unref (image);
/* check that callback setting texture was actually called, as its technically async */
g_assert (texture);
#ifdef G_ENABLE_DEBUG
start_time = gsk_profiler_timer_get_start (profiler, self->profile_timers.cpu_time);
cpu_time = gsk_profiler_timer_end (profiler, self->profile_timers.cpu_time);
gsk_profiler_timer_set (profiler, self->profile_timers.cpu_time, cpu_time);
gsk_profiler_push_samples (profiler);
if (GDK_PROFILER_IS_RUNNING)
{
gdk_profiler_add_mark (start_time * 1000, cpu_time * 1000, "render", "");
gdk_profiler_set_int_counter (texture_pixels_counter,
gsk_profiler_counter_get (profiler, self->profile_counters.texture_pixels));
gdk_profiler_set_int_counter (fallback_pixels_counter,
gsk_profiler_counter_get (profiler, self->profile_counters.fallback_pixels));
}
#endif
return texture;
}
static void
gsk_vulkan_renderer_render (GskRenderer *renderer,
GskRenderNode *root,
const cairo_region_t *region)
{
GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
GskVulkanRender *render;
GdkSurface *surface;
cairo_region_t *render_region;
#ifdef G_ENABLE_DEBUG
GskProfiler *profiler;
gint64 cpu_time;
#endif
uint32_t draw_index;
#ifdef G_ENABLE_DEBUG
profiler = gsk_renderer_get_profiler (renderer);
gsk_profiler_counter_set (profiler, self->profile_counters.fallback_pixels, 0);
gsk_profiler_counter_set (profiler, self->profile_counters.texture_pixels, 0);
gsk_profiler_counter_set (profiler, self->profile_counters.render_passes, 0);
gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
#endif
gdk_draw_context_begin_frame_full (GDK_DRAW_CONTEXT (self->vulkan),
gsk_render_node_get_preferred_depth (root),
region);
render = gsk_vulkan_renderer_get_render (self);
surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self->vulkan));
render_region = get_render_region (self);
draw_index = gdk_vulkan_context_get_draw_index (self->vulkan);
gsk_vulkan_render_render (render,
self->targets[draw_index],
&GRAPHENE_RECT_INIT(
0, 0,
gdk_surface_get_width (surface),
gdk_surface_get_height (surface)
),
render_region,
root,
NULL, NULL);
#ifdef G_ENABLE_DEBUG
gsk_profiler_counter_inc (profiler, self->profile_counters.frames);
cpu_time = gsk_profiler_timer_end (profiler, self->profile_timers.cpu_time);
gsk_profiler_timer_set (profiler, self->profile_timers.cpu_time, cpu_time);
gsk_profiler_push_samples (profiler);
#endif
gdk_draw_context_end_frame (GDK_DRAW_CONTEXT (self->vulkan));
g_clear_pointer (&render_region, cairo_region_destroy);
}
static void
gsk_vulkan_renderer_class_init (GskVulkanRendererClass *klass)
{
GskRendererClass *renderer_class = GSK_RENDERER_CLASS (klass);
renderer_class->realize = gsk_vulkan_renderer_realize;
renderer_class->unrealize = gsk_vulkan_renderer_unrealize;
renderer_class->render = gsk_vulkan_renderer_render;
renderer_class->render_texture = gsk_vulkan_renderer_render_texture;
}
static void
gsk_vulkan_renderer_init (GskVulkanRenderer *self)
{
#ifdef G_ENABLE_DEBUG
GskProfiler *profiler = gsk_renderer_get_profiler (GSK_RENDERER (self));
#endif
gsk_ensure_resources ();
#ifdef G_ENABLE_DEBUG
self->profile_counters.frames = gsk_profiler_add_counter (profiler, "frames", "Frames", FALSE);
self->profile_counters.render_passes = gsk_profiler_add_counter (profiler, "render-passes", "Render passes", FALSE);
self->profile_counters.fallback_pixels = gsk_profiler_add_counter (profiler, "fallback-pixels", "Fallback pixels", TRUE);
self->profile_counters.texture_pixels = gsk_profiler_add_counter (profiler, "texture-pixels", "Texture pixels", TRUE);
self->profile_timers.cpu_time = gsk_profiler_add_timer (profiler, "cpu-time", "CPU time", FALSE, TRUE);
if (GSK_RENDERER_DEBUG_CHECK (GSK_RENDERER (self), SYNC))
self->profile_timers.gpu_time = gsk_profiler_add_timer (profiler, "gpu-time", "GPU time", FALSE, TRUE);
if (texture_pixels_counter == 0)
{
texture_pixels_counter = gdk_profiler_define_int_counter ("texture-pixels", "Texture Pixels");
fallback_pixels_counter = gdk_profiler_define_int_counter ("fallback-pixels", "Fallback Pixels");
}
#endif
}
static void
gsk_vulkan_renderer_clear_texture (gpointer p)
{
GskVulkanTextureData *data = p;
if (data->renderer != NULL)
data->renderer->textures = g_slist_remove (data->renderer->textures, data);
g_object_unref (data->image);
g_free (data);
}
GskVulkanImage *
gsk_vulkan_renderer_get_texture_image (GskVulkanRenderer *self,
GdkTexture *texture)
{
GskVulkanTextureData *data;
data = gdk_texture_get_render_data (texture, self);
if (data)
return data->image;
return NULL;
}
void
gsk_vulkan_renderer_add_texture_image (GskVulkanRenderer *self,
GdkTexture *texture,
GskVulkanImage *image)
{
GskVulkanTextureData *data;
data = g_new0 (GskVulkanTextureData, 1);
data->image = image;
data->texture = texture;
data->renderer = self;
if (gdk_texture_set_render_data (texture, self, data, gsk_vulkan_renderer_clear_texture))
{
g_object_ref (data->image);
self->textures = g_slist_prepend (self->textures, data);
}
else
{
g_free (data);
}
}
GskVulkanGlyphCache *
gsk_vulkan_renderer_get_glyph_cache (GskVulkanRenderer *self)
{
return self->glyph_cache;
}
/**
* gsk_vulkan_renderer_new:
*
* Creates a new Vulkan renderer.
*
* The Vulkan renderer is a renderer that uses the Vulkan library for
* rendering.
*
* This function is only available when GTK was compiled with Vulkan
* support.
*
* Returns: a new Vulkan renderer
**/
GskRenderer *
gsk_vulkan_renderer_new (void)
{
return g_object_new (GSK_TYPE_VULKAN_RENDERER, NULL);
}

View File

@ -1,54 +0,0 @@
/*
* Copyright © 2016 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <gdk/gdk.h>
#include <gsk/gsk.h>
#ifdef GDK_RENDERING_VULKAN
#include <vulkan/vulkan.h>
G_BEGIN_DECLS
#define GSK_TYPE_VULKAN_RENDERER (gsk_vulkan_renderer_get_type ())
#define GSK_VULKAN_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_VULKAN_RENDERER, GskVulkanRenderer))
#define GSK_IS_VULKAN_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_VULKAN_RENDERER))
#define GSK_VULKAN_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_VULKAN_RENDERER, GskVulkanRendererClass))
#define GSK_IS_VULKAN_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_VULKAN_RENDERER))
#define GSK_VULKAN_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_VULKAN_RENDERER, GskVulkanRendererClass))
/**
* GskVulkanRenderer:
*
* A GSK renderer that is using Vulkan.
*/
typedef struct _GskVulkanRenderer GskVulkanRenderer;
typedef struct _GskVulkanRendererClass GskVulkanRendererClass;
GDK_AVAILABLE_IN_ALL
GType gsk_vulkan_renderer_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GskRenderer * gsk_vulkan_renderer_new (void);
G_END_DECLS
#endif /* GDK_RENDERING_VULKAN */

View File

@ -1,19 +0,0 @@
#pragma once
#include "gskvulkanrenderer.h"
#include "gskvulkanglyphcacheprivate.h"
#include "gskvulkanimageprivate.h"
G_BEGIN_DECLS
GskVulkanImage * gsk_vulkan_renderer_get_texture_image (GskVulkanRenderer *self,
GdkTexture *texture);
void gsk_vulkan_renderer_add_texture_image (GskVulkanRenderer *self,
GdkTexture *texture,
GskVulkanImage *image);
GskVulkanGlyphCache * gsk_vulkan_renderer_get_glyph_cache (GskVulkanRenderer *self);
G_END_DECLS

File diff suppressed because it is too large Load Diff

View File

@ -1,314 +0,0 @@
#include "config.h"
#include "gskvulkanrenderpassopprivate.h"
#include "gskrendernodeprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanshaderopprivate.h"
#include "gdk/gdkvulkancontextprivate.h"
typedef struct _GskVulkanRenderPassOp GskVulkanRenderPassOp;
struct _GskVulkanRenderPassOp
{
GskVulkanOp op;
GskVulkanImage *image;
cairo_rectangle_int_t area;
VkImageLayout initial_layout;
VkImageLayout final_layout;
};
static void
gsk_vulkan_render_pass_op_finish (GskVulkanOp *op)
{
GskVulkanRenderPassOp *self = (GskVulkanRenderPassOp *) op;
g_object_unref (self->image);
}
static void
gsk_vulkan_render_pass_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanRenderPassOp *self = (GskVulkanRenderPassOp *) op;
print_indent (string, indent);
g_string_append_printf (string, "begin-render-pass %zux%zu ",
gsk_vulkan_image_get_width (self->image),
gsk_vulkan_image_get_height (self->image));
print_newline (string);
}
static gsize
gsk_vulkan_render_pass_op_count_vertex_data (GskVulkanOp *op,
gsize n_bytes)
{
return n_bytes;
}
static void
gsk_vulkan_render_pass_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
}
static void
gsk_vulkan_render_pass_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
}
static void
gsk_vulkan_render_pass_op_do_barriers (GskVulkanRenderPassOp *self,
VkCommandBuffer command_buffer)
{
GskVulkanShaderOp *shader;
GskVulkanOp *op;
gsize i;
for (op = ((GskVulkanOp *) self)->next;
op->op_class->stage != GSK_VULKAN_STAGE_END_PASS;
op = op->next)
{
if (op->op_class->stage != GSK_VULKAN_STAGE_SHADER)
continue;
shader = (GskVulkanShaderOp *) op;
for (i = 0; i < ((GskVulkanShaderOpClass *) op->op_class)->n_images; i++)
{
gsk_vulkan_image_transition (shader->images[i],
command_buffer,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_ACCESS_SHADER_READ_BIT);
}
}
}
static GskVulkanOp *
gsk_vulkan_render_pass_op_command (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer)
{
GskVulkanRenderPassOp *self = (GskVulkanRenderPassOp *) op;
VkRenderPass vk_render_pass;
/* nesting render passes not allowed */
g_assert (render_pass == VK_NULL_HANDLE);
gsk_vulkan_render_pass_op_do_barriers (self, command_buffer);
vk_render_pass = gsk_vulkan_render_get_render_pass (render,
gsk_vulkan_image_get_vk_format (self->image),
self->initial_layout,
self->final_layout);
vkCmdSetViewport (command_buffer,
0,
1,
&(VkViewport) {
.x = 0,
.y = 0,
.width = gsk_vulkan_image_get_width (self->image),
.height = gsk_vulkan_image_get_height (self->image),
.minDepth = 0,
.maxDepth = 1
});
vkCmdBeginRenderPass (command_buffer,
&(VkRenderPassBeginInfo) {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.renderPass = vk_render_pass,
.framebuffer = gsk_vulkan_image_get_framebuffer (self->image,
vk_render_pass),
.renderArea = {
{ self->area.x, self->area.y },
{ self->area.width, self->area.height }
},
.clearValueCount = 1,
.pClearValues = (VkClearValue [1]) {
{ .color = { .float32 = { 0.f, 0.f, 0.f, 0.f } } }
}
},
VK_SUBPASS_CONTENTS_INLINE);
op = op->next;
while (op->op_class->stage != GSK_VULKAN_STAGE_END_PASS)
{
op = gsk_vulkan_op_command (op, render, vk_render_pass, command_buffer);
}
op = gsk_vulkan_op_command (op, render, vk_render_pass, command_buffer);
return op;
}
static const GskVulkanOpClass GSK_VULKAN_RENDER_PASS_OP_CLASS = {
GSK_VULKAN_OP_SIZE (GskVulkanRenderPassOp),
GSK_VULKAN_STAGE_BEGIN_PASS,
gsk_vulkan_render_pass_op_finish,
gsk_vulkan_render_pass_op_print,
gsk_vulkan_render_pass_op_count_vertex_data,
gsk_vulkan_render_pass_op_collect_vertex_data,
gsk_vulkan_render_pass_op_reserve_descriptor_sets,
gsk_vulkan_render_pass_op_command
};
typedef struct _GskVulkanRenderPassEndOp GskVulkanRenderPassEndOp;
struct _GskVulkanRenderPassEndOp
{
GskVulkanOp op;
GskVulkanImage *image;
VkImageLayout final_layout;
};
static void
gsk_vulkan_render_pass_end_op_finish (GskVulkanOp *op)
{
GskVulkanRenderPassEndOp *self = (GskVulkanRenderPassEndOp *) op;
g_object_unref (self->image);
}
static void
gsk_vulkan_render_pass_end_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanRenderPassEndOp *self = (GskVulkanRenderPassEndOp *) op;
print_indent (string, indent);
g_string_append_printf (string, "end-render-pass ");
print_image (string, self->image);
print_newline (string);
}
static gsize
gsk_vulkan_render_pass_end_op_count_vertex_data (GskVulkanOp *op,
gsize n_bytes)
{
return n_bytes;
}
static void
gsk_vulkan_render_pass_end_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
}
static void
gsk_vulkan_render_pass_end_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
}
static GskVulkanOp *
gsk_vulkan_render_pass_end_op_command (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer)
{
GskVulkanRenderPassEndOp *self = (GskVulkanRenderPassEndOp *) op;
vkCmdEndRenderPass (command_buffer);
gsk_vulkan_image_set_vk_image_layout (self->image,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
self->final_layout,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
return op->next;
}
static const GskVulkanOpClass GSK_VULKAN_RENDER_PASS_END_OP_CLASS = {
GSK_VULKAN_OP_SIZE (GskVulkanRenderPassEndOp),
GSK_VULKAN_STAGE_END_PASS,
gsk_vulkan_render_pass_end_op_finish,
gsk_vulkan_render_pass_end_op_print,
gsk_vulkan_render_pass_end_op_count_vertex_data,
gsk_vulkan_render_pass_end_op_collect_vertex_data,
gsk_vulkan_render_pass_end_op_reserve_descriptor_sets,
gsk_vulkan_render_pass_end_op_command
};
void
gsk_vulkan_render_pass_begin_op (GskVulkanRender *render,
GskVulkanImage *image,
const cairo_rectangle_int_t *area,
VkImageLayout initial_layout,
VkImageLayout final_layout)
{
GskVulkanRenderPassOp *self;
self = (GskVulkanRenderPassOp *) gsk_vulkan_op_alloc (render, &GSK_VULKAN_RENDER_PASS_OP_CLASS);
self->image = g_object_ref (image);
self->initial_layout = initial_layout;
self->final_layout = final_layout;
self->area = *area;
}
void
gsk_vulkan_render_pass_end_op (GskVulkanRender *render,
GskVulkanImage *image,
VkImageLayout final_layout)
{
GskVulkanRenderPassEndOp *self;
self = (GskVulkanRenderPassEndOp *) gsk_vulkan_op_alloc (render, &GSK_VULKAN_RENDER_PASS_END_OP_CLASS);
self->image = g_object_ref (image);
self->final_layout = final_layout;
}
GskVulkanImage *
gsk_vulkan_render_pass_op_offscreen (GskVulkanRender *render,
const graphene_vec2_t *scale,
const graphene_rect_t *viewport,
GskRenderNode *node)
{
GskVulkanRenderPass *render_pass;
GdkVulkanContext *context;
GskVulkanImage *image;
int width, height;
width = ceil (graphene_vec2_get_x (scale) * viewport->size.width);
height = ceil (graphene_vec2_get_y (scale) * viewport->size.height);
context = gsk_vulkan_render_get_context (render);
image = gsk_vulkan_image_new_for_offscreen (context,
gdk_vulkan_context_get_offscreen_format (context,
gsk_render_node_get_preferred_depth (node)),
width, height);
gsk_vulkan_render_pass_begin_op (render,
image,
&(cairo_rectangle_int_t) { 0, 0, width, height },
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
render_pass = gsk_vulkan_render_pass_new ();
gsk_vulkan_render_pass_add (render_pass,
render,
width, height,
&(cairo_rectangle_int_t) { 0, 0, width, height },
node,
viewport);
gsk_vulkan_render_pass_free (render_pass);
gsk_vulkan_render_pass_end_op (render,
image,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
g_object_unref (image);
return image;
}

View File

@ -1,23 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_render_pass_begin_op (GskVulkanRender *render,
GskVulkanImage *image,
const cairo_rectangle_int_t *area,
VkImageLayout initial_layout,
VkImageLayout final_layout);
void gsk_vulkan_render_pass_end_op (GskVulkanRender *render,
GskVulkanImage *image,
VkImageLayout final_layout);
GskVulkanImage * gsk_vulkan_render_pass_op_offscreen (GskVulkanRender *render,
const graphene_vec2_t *scale,
const graphene_rect_t *viewport,
GskRenderNode *node);
G_END_DECLS

View File

@ -1,26 +0,0 @@
#pragma once
#include <gdk/gdk.h>
#include <gsk/gskrendernode.h>
#include "gskvulkanbufferprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanrenderprivate.h"
G_BEGIN_DECLS
GskVulkanRenderPass * gsk_vulkan_render_pass_new (void);
void gsk_vulkan_render_pass_free (GskVulkanRenderPass *self);
void gsk_vulkan_render_pass_add (GskVulkanRenderPass *self,
GskVulkanRender *render,
int width,
int height,
cairo_rectangle_int_t *clip,
GskRenderNode *node,
const graphene_rect_t *viewport);
G_END_DECLS

View File

@ -1,67 +0,0 @@
#pragma once
#include <gdk/gdk.h>
#include <gsk/gskrendernode.h>
#include "gskvulkanclipprivate.h"
#include "gskvulkanimageprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanrenderpassprivate.h"
G_BEGIN_DECLS
typedef enum {
GSK_VULKAN_SAMPLER_DEFAULT,
GSK_VULKAN_SAMPLER_REPEAT,
GSK_VULKAN_SAMPLER_NEAREST
} GskVulkanRenderSampler;
typedef void (* GskVulkanDownloadFunc) (gpointer user_data,
GdkMemoryFormat format,
const guchar *data,
int width,
int height,
gsize stride);
GskVulkanRender * gsk_vulkan_render_new (GskRenderer *renderer,
GdkVulkanContext *context);
void gsk_vulkan_render_free (GskVulkanRender *self);
gboolean gsk_vulkan_render_is_busy (GskVulkanRender *self);
void gsk_vulkan_render_render (GskVulkanRender *self,
GskVulkanImage *target,
const graphene_rect_t *rect,
const cairo_region_t *clip,
GskRenderNode *node,
GskVulkanDownloadFunc download_func,
gpointer download_data);
GskRenderer * gsk_vulkan_render_get_renderer (GskVulkanRender *self);
GdkVulkanContext * gsk_vulkan_render_get_context (GskVulkanRender *self);
gpointer gsk_vulkan_render_alloc_op (GskVulkanRender *self,
gsize size);
VkPipelineLayout gsk_vulkan_render_get_pipeline_layout (GskVulkanRender *self);
VkPipeline gsk_vulkan_render_get_pipeline (GskVulkanRender *self,
const GskVulkanOpClass *op_class,
GskVulkanShaderClip clip,
VkRenderPass render_pass);
VkRenderPass gsk_vulkan_render_get_render_pass (GskVulkanRender *self,
VkFormat format,
VkImageLayout from_layout,
VkImageLayout to_layout);
gsize gsk_vulkan_render_get_image_descriptor (GskVulkanRender *self,
GskVulkanImage *source,
GskVulkanRenderSampler render_sampler);
gsize gsk_vulkan_render_get_buffer_descriptor (GskVulkanRender *self,
GskVulkanBuffer *buffer);
guchar * gsk_vulkan_render_get_buffer_memory (GskVulkanRender *self,
gsize size,
gsize alignment,
gsize *out_offset);
VkFence gsk_vulkan_render_get_fence (GskVulkanRender *self);
G_END_DECLS

View File

@ -1,92 +0,0 @@
#include "config.h"
#include "gskvulkanscissoropprivate.h"
#include "gskvulkanprivate.h"
typedef struct _GskVulkanScissorOp GskVulkanScissorOp;
struct _GskVulkanScissorOp
{
GskVulkanOp op;
cairo_rectangle_int_t rect;
};
static void
gsk_vulkan_scissor_op_finish (GskVulkanOp *op)
{
}
static void
gsk_vulkan_scissor_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanScissorOp *self = (GskVulkanScissorOp *) op;
print_indent (string, indent);
print_int_rect (string, &self->rect);
g_string_append_printf (string, "scissor ");
print_newline (string);
}
static gsize
gsk_vulkan_scissor_op_count_vertex_data (GskVulkanOp *op,
gsize n_bytes)
{
return n_bytes;
}
static void
gsk_vulkan_scissor_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
}
static void
gsk_vulkan_scissor_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
}
static GskVulkanOp *
gsk_vulkan_scissor_op_command (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer)
{
GskVulkanScissorOp *self = (GskVulkanScissorOp *) op;
vkCmdSetScissor (command_buffer,
0,
1,
&(VkRect2D) {
{ self->rect.x, self->rect.y },
{ self->rect.width, self->rect.height },
});
return op->next;
}
static const GskVulkanOpClass GSK_VULKAN_SCISSOR_OP_CLASS = {
GSK_VULKAN_OP_SIZE (GskVulkanScissorOp),
GSK_VULKAN_STAGE_COMMAND,
gsk_vulkan_scissor_op_finish,
gsk_vulkan_scissor_op_print,
gsk_vulkan_scissor_op_count_vertex_data,
gsk_vulkan_scissor_op_collect_vertex_data,
gsk_vulkan_scissor_op_reserve_descriptor_sets,
gsk_vulkan_scissor_op_command
};
void
gsk_vulkan_scissor_op (GskVulkanRender *render,
const cairo_rectangle_int_t *rect)
{
GskVulkanScissorOp *self;
self = (GskVulkanScissorOp *) gsk_vulkan_op_alloc (render, &GSK_VULKAN_SCISSOR_OP_CLASS);
self->rect = *rect;
}

View File

@ -1,12 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_scissor_op (GskVulkanRender *render,
const cairo_rectangle_int_t *rect);
G_END_DECLS

View File

@ -1,102 +0,0 @@
#include "config.h"
#include "gskvulkanshaderopprivate.h"
void
gsk_vulkan_shader_op_finish (GskVulkanOp *op)
{
GskVulkanShaderOpClass *shader_op_class = ((GskVulkanShaderOpClass *) op->op_class);
GskVulkanShaderOp *self = (GskVulkanShaderOp *) op;
gsize i;
for (i = 0; i < shader_op_class->n_images; i++)
g_object_unref (self->images[i]);
}
static inline gsize
round_up (gsize number, gsize divisor)
{
return (number + divisor - 1) / divisor * divisor;
}
gsize
gsk_vulkan_shader_op_count_vertex_data (GskVulkanOp *op,
gsize n_bytes)
{
GskVulkanShaderOp *self = (GskVulkanShaderOp *) op;
GskVulkanShaderOpClass *shader_op_class = ((GskVulkanShaderOpClass *) op->op_class);
gsize vertex_stride;
vertex_stride = shader_op_class->vertex_input_state->pVertexBindingDescriptions[0].stride;
n_bytes = round_up (n_bytes, vertex_stride);
self->vertex_offset = n_bytes;
n_bytes += vertex_stride;
return n_bytes;
}
GskVulkanOp *
gsk_vulkan_shader_op_command_n (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer,
gsize instance_scale)
{
GskVulkanShaderOp *self = (GskVulkanShaderOp *) op;
GskVulkanShaderOpClass *shader_op_class = ((GskVulkanShaderOpClass *) op->op_class);
GskVulkanOp *next;
gsize stride = shader_op_class->vertex_input_state->pVertexBindingDescriptions[0].stride;
gsize i;
i = 1;
for (next = op->next; next && i < 10 * 1000; next = next->next)
{
GskVulkanShaderOp *next_shader = (GskVulkanShaderOp *) next;
if (next->op_class != op->op_class ||
next_shader->vertex_offset != self->vertex_offset + i * stride)
break;
i++;
}
vkCmdBindPipeline (command_buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
gsk_vulkan_render_get_pipeline (render,
op->op_class,
self->clip,
render_pass));
vkCmdDraw (command_buffer,
6 * instance_scale, i,
0, self->vertex_offset / stride);
return next;
}
GskVulkanOp *
gsk_vulkan_shader_op_command (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer)
{
return gsk_vulkan_shader_op_command_n (op, render, render_pass, command_buffer, 1);
}
GskVulkanShaderOp *
gsk_vulkan_shader_op_alloc (GskVulkanRender *render,
const GskVulkanShaderOpClass *op_class,
GskVulkanShaderClip clip,
GskVulkanImage **images)
{
GskVulkanShaderOp *self;
gsize i;
self = (GskVulkanShaderOp *) gsk_vulkan_op_alloc (render, &op_class->parent_class);
self->clip = clip;
for (i = 0; i < op_class->n_images; i++)
self->images[i] = g_object_ref (images[i]);
return self;
}

View File

@ -1,49 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
#include "gskvulkanclipprivate.h"
G_BEGIN_DECLS
typedef struct _GskVulkanShaderOp GskVulkanShaderOp;
typedef struct _GskVulkanShaderOpClass GskVulkanShaderOpClass;
struct _GskVulkanShaderOp
{
GskVulkanOp parent_op;
GskVulkanShaderClip clip;
gsize vertex_offset;
GskVulkanImage *images[2];
};
struct _GskVulkanShaderOpClass
{
GskVulkanOpClass parent_class;
const char * shader_name;
gsize n_images;
const VkPipelineVertexInputStateCreateInfo *vertex_input_state;
};
GskVulkanShaderOp * gsk_vulkan_shader_op_alloc (GskVulkanRender *render,
const GskVulkanShaderOpClass *op_class,
GskVulkanShaderClip clip,
GskVulkanImage **images);
void gsk_vulkan_shader_op_finish (GskVulkanOp *op);
gsize gsk_vulkan_shader_op_count_vertex_data (GskVulkanOp *op,
gsize n_bytes);
GskVulkanOp * gsk_vulkan_shader_op_command_n (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer,
gsize instance_scale);
GskVulkanOp * gsk_vulkan_shader_op_command (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer);
G_END_DECLS

View File

@ -1,101 +0,0 @@
#include "config.h"
#include "gskvulkantextureopprivate.h"
#include "gskvulkanprivate.h"
#include "gskvulkanshaderopprivate.h"
#include "vulkan/resources/texture.vert.h"
typedef struct _GskVulkanTextureOp GskVulkanTextureOp;
struct _GskVulkanTextureOp
{
GskVulkanShaderOp op;
GskVulkanRenderSampler sampler;
graphene_rect_t rect;
graphene_rect_t tex_rect;
guint32 image_descriptor;
};
static void
gsk_vulkan_texture_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanTextureOp *self = (GskVulkanTextureOp *) op;
GskVulkanShaderOp *shader = (GskVulkanShaderOp *) op;
print_indent (string, indent);
print_rect (string, &self->rect);
g_string_append (string, "texture ");
print_image (string, shader->images[0]);
print_newline (string);
}
static void
gsk_vulkan_texture_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
GskVulkanTextureOp *self = (GskVulkanTextureOp *) op;
GskVulkanTextureInstance *instance = (GskVulkanTextureInstance *) (data + ((GskVulkanShaderOp *) op)->vertex_offset);
instance->rect[0] = self->rect.origin.x;
instance->rect[1] = self->rect.origin.y;
instance->rect[2] = self->rect.size.width;
instance->rect[3] = self->rect.size.height;
instance->tex_rect[0] = self->tex_rect.origin.x;
instance->tex_rect[1] = self->tex_rect.origin.y;
instance->tex_rect[2] = self->tex_rect.size.width;
instance->tex_rect[3] = self->tex_rect.size.height;
instance->tex_id = self->image_descriptor;
}
static void
gsk_vulkan_texture_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
GskVulkanTextureOp *self = (GskVulkanTextureOp *) op;
GskVulkanShaderOp *shader = (GskVulkanShaderOp *) op;
self->image_descriptor = gsk_vulkan_render_get_image_descriptor (render, shader->images[0], self->sampler);
}
static const GskVulkanShaderOpClass GSK_VULKAN_TEXTURE_OP_CLASS = {
{
GSK_VULKAN_OP_SIZE (GskVulkanTextureOp),
GSK_VULKAN_STAGE_SHADER,
gsk_vulkan_shader_op_finish,
gsk_vulkan_texture_op_print,
gsk_vulkan_shader_op_count_vertex_data,
gsk_vulkan_texture_op_collect_vertex_data,
gsk_vulkan_texture_op_reserve_descriptor_sets,
gsk_vulkan_shader_op_command
},
"texture",
1,
&gsk_vulkan_texture_info,
};
void
gsk_vulkan_texture_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
GskVulkanImage *image,
GskVulkanRenderSampler sampler,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect)
{
GskVulkanTextureOp *self;
self = (GskVulkanTextureOp *) gsk_vulkan_shader_op_alloc (render,
&GSK_VULKAN_TEXTURE_OP_CLASS,
clip,
&image);
self->sampler = sampler;
graphene_rect_offset_r (rect, offset->x, offset->y, &self->rect);
gsk_vulkan_normalize_tex_coords (&self->tex_rect, rect, tex_rect);
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
void gsk_vulkan_texture_op (GskVulkanRender *render,
GskVulkanShaderClip clip,
GskVulkanImage *image,
GskVulkanRenderSampler sampler,
const graphene_rect_t *rect,
const graphene_point_t *offset,
const graphene_rect_t *tex_rect);
G_END_DECLS

View File

@ -1,478 +0,0 @@
#include "config.h"
#include "gskvulkanuploadopprivate.h"
#include "gskvulkanprivate.h"
#include "gdk/gdkmemoryformatprivate.h"
static gsize
gsk_vulkan_upload_op_count_vertex_data (GskVulkanOp *op,
gsize n_bytes)
{
return n_bytes;
}
static void
gsk_vulkan_upload_op_collect_vertex_data (GskVulkanOp *op,
guchar *data)
{
}
static void
gsk_vulkan_upload_op_reserve_descriptor_sets (GskVulkanOp *op,
GskVulkanRender *render)
{
}
static GskVulkanOp *
gsk_vulkan_upload_op_command_with_area (GskVulkanOp *op,
GskVulkanRender *render,
VkCommandBuffer command_buffer,
GskVulkanImage *image,
const cairo_rectangle_int_t *area,
void (* draw_func) (GskVulkanOp *, guchar *, gsize),
GskVulkanBuffer **buffer)
{
gsize stride;
guchar *data;
stride = area->width * gdk_memory_format_bytes_per_pixel (gsk_vulkan_image_get_format (image));
*buffer = gsk_vulkan_buffer_new_map (gsk_vulkan_render_get_context (render),
area->height * stride,
GSK_VULKAN_WRITE);
data = gsk_vulkan_buffer_map (*buffer);
draw_func (op, data, stride);
gsk_vulkan_buffer_unmap (*buffer);
vkCmdPipelineBarrier (command_buffer,
VK_PIPELINE_STAGE_HOST_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
0,
0, NULL,
1, &(VkBufferMemoryBarrier) {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT,
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = gsk_vulkan_buffer_get_buffer (*buffer),
.offset = 0,
.size = VK_WHOLE_SIZE,
},
0, NULL);
gsk_vulkan_image_transition (image,
command_buffer,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_ACCESS_TRANSFER_WRITE_BIT);
vkCmdCopyBufferToImage (command_buffer,
gsk_vulkan_buffer_get_buffer (*buffer),
gsk_vulkan_image_get_vk_image (image),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
(VkBufferImageCopy[1]) {
{
.bufferOffset = 0,
.bufferRowLength = area->width,
.bufferImageHeight = area->height,
.imageSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = 1
},
.imageOffset = {
.x = area->x,
.y = area->y,
.z = 0
},
.imageExtent = {
.width = area->width,
.height = area->height,
.depth = 1
}
}
});
return op->next;
}
static GskVulkanOp *
gsk_vulkan_upload_op_command (GskVulkanOp *op,
GskVulkanRender *render,
VkCommandBuffer command_buffer,
GskVulkanImage *image,
void (* draw_func) (GskVulkanOp *, guchar *, gsize),
GskVulkanBuffer **buffer)
{
gsize stride;
guchar *data;
data = gsk_vulkan_image_try_map (image, &stride);
if (data)
{
draw_func (op, data, stride);
gsk_vulkan_image_unmap (image);
*buffer = NULL;
return op->next;
}
return gsk_vulkan_upload_op_command_with_area (op,
render,
command_buffer,
image,
&(cairo_rectangle_int_t) {
0, 0,
gsk_vulkan_image_get_width (image),
gsk_vulkan_image_get_height (image),
},
draw_func,
buffer);
}
typedef struct _GskVulkanUploadTextureOp GskVulkanUploadTextureOp;
struct _GskVulkanUploadTextureOp
{
GskVulkanOp op;
GskVulkanImage *image;
GskVulkanBuffer *buffer;
GdkTexture *texture;
};
static void
gsk_vulkan_upload_texture_op_finish (GskVulkanOp *op)
{
GskVulkanUploadTextureOp *self = (GskVulkanUploadTextureOp *) op;
g_object_unref (self->image);
g_clear_pointer (&self->buffer, gsk_vulkan_buffer_free);
g_object_unref (self->texture);
}
static void
gsk_vulkan_upload_texture_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanUploadTextureOp *self = (GskVulkanUploadTextureOp *) op;
print_indent (string, indent);
g_string_append (string, "upload-texture ");
print_image (string, self->image);
print_newline (string);
}
static void
gsk_vulkan_upload_texture_op_draw (GskVulkanOp *op,
guchar *data,
gsize stride)
{
GskVulkanUploadTextureOp *self = (GskVulkanUploadTextureOp *) op;
GdkTextureDownloader *downloader;
downloader = gdk_texture_downloader_new (self->texture);
gdk_texture_downloader_set_format (downloader, gsk_vulkan_image_get_format (self->image));
gdk_texture_downloader_download_into (downloader, data, stride);
gdk_texture_downloader_free (downloader);
}
static GskVulkanOp *
gsk_vulkan_upload_texture_op_command (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer)
{
GskVulkanUploadTextureOp *self = (GskVulkanUploadTextureOp *) op;
return gsk_vulkan_upload_op_command (op,
render,
command_buffer,
self->image,
gsk_vulkan_upload_texture_op_draw,
&self->buffer);
}
static const GskVulkanOpClass GSK_VULKAN_UPLOAD_TEXTURE_OP_CLASS = {
GSK_VULKAN_OP_SIZE (GskVulkanUploadTextureOp),
GSK_VULKAN_STAGE_UPLOAD,
gsk_vulkan_upload_texture_op_finish,
gsk_vulkan_upload_texture_op_print,
gsk_vulkan_upload_op_count_vertex_data,
gsk_vulkan_upload_op_collect_vertex_data,
gsk_vulkan_upload_op_reserve_descriptor_sets,
gsk_vulkan_upload_texture_op_command
};
GskVulkanImage *
gsk_vulkan_upload_texture_op (GskVulkanRender *render,
GdkTexture *texture)
{
GskVulkanUploadTextureOp *self;
self = (GskVulkanUploadTextureOp *) gsk_vulkan_op_alloc (render, &GSK_VULKAN_UPLOAD_TEXTURE_OP_CLASS);
self->texture = g_object_ref (texture);
self->image = gsk_vulkan_image_new_for_upload (gsk_vulkan_render_get_context (render),
gdk_texture_get_format (texture),
gdk_texture_get_width (texture),
gdk_texture_get_height (texture));
return self->image;
}
typedef struct _GskVulkanUploadCairoOp GskVulkanUploadCairoOp;
struct _GskVulkanUploadCairoOp
{
GskVulkanOp op;
GskVulkanImage *image;
GskRenderNode *node;
graphene_rect_t viewport;
GskVulkanBuffer *buffer;
};
static void
gsk_vulkan_upload_cairo_op_finish (GskVulkanOp *op)
{
GskVulkanUploadCairoOp *self = (GskVulkanUploadCairoOp *) op;
g_object_unref (self->image);
gsk_render_node_unref (self->node);
g_clear_pointer (&self->buffer, gsk_vulkan_buffer_free);
}
static void
gsk_vulkan_upload_cairo_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanUploadCairoOp *self = (GskVulkanUploadCairoOp *) op;
print_indent (string, indent);
g_string_append (string, "upload-cairo ");
print_image (string, self->image);
print_newline (string);
}
static void
gsk_vulkan_upload_cairo_op_draw (GskVulkanOp *op,
guchar *data,
gsize stride)
{
GskVulkanUploadCairoOp *self = (GskVulkanUploadCairoOp *) op;
cairo_surface_t *surface;
cairo_t *cr;
int width, height;
width = gsk_vulkan_image_get_width (self->image);
height = gsk_vulkan_image_get_height (self->image);
surface = cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_ARGB32,
width, height,
stride);
cairo_surface_set_device_scale (surface,
width / self->viewport.size.width,
height / self->viewport.size.height);
cr = cairo_create (surface);
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
cairo_paint (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
cairo_translate (cr, -self->viewport.origin.x, -self->viewport.origin.y);
gsk_render_node_draw (self->node, cr);
cairo_destroy (cr);
cairo_surface_finish (surface);
cairo_surface_destroy (surface);
}
static GskVulkanOp *
gsk_vulkan_upload_cairo_op_command (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer)
{
GskVulkanUploadCairoOp *self = (GskVulkanUploadCairoOp *) op;
return gsk_vulkan_upload_op_command (op,
render,
command_buffer,
self->image,
gsk_vulkan_upload_cairo_op_draw,
&self->buffer);
}
static const GskVulkanOpClass GSK_VULKAN_UPLOAD_CAIRO_OP_CLASS = {
GSK_VULKAN_OP_SIZE (GskVulkanUploadCairoOp),
GSK_VULKAN_STAGE_UPLOAD,
gsk_vulkan_upload_cairo_op_finish,
gsk_vulkan_upload_cairo_op_print,
gsk_vulkan_upload_op_count_vertex_data,
gsk_vulkan_upload_op_collect_vertex_data,
gsk_vulkan_upload_op_reserve_descriptor_sets,
gsk_vulkan_upload_cairo_op_command
};
GskVulkanImage *
gsk_vulkan_upload_cairo_op (GskVulkanRender *render,
GskRenderNode *node,
const graphene_vec2_t *scale,
const graphene_rect_t *viewport)
{
GskVulkanUploadCairoOp *self;
self = (GskVulkanUploadCairoOp *) gsk_vulkan_op_alloc (render, &GSK_VULKAN_UPLOAD_CAIRO_OP_CLASS);
self->node = gsk_render_node_ref (node);
self->image = gsk_vulkan_image_new_for_upload (gsk_vulkan_render_get_context (render),
GDK_MEMORY_DEFAULT,
ceil (graphene_vec2_get_x (scale) * viewport->size.width),
ceil (graphene_vec2_get_y (scale) * viewport->size.height));
g_assert (gsk_vulkan_image_get_postprocess (self->image) == 0);
self->viewport = *viewport;
return self->image;
}
typedef struct _GskVulkanUploadGlyphOp GskVulkanUploadGlyphOp;
struct _GskVulkanUploadGlyphOp
{
GskVulkanOp op;
GskVulkanImage *image;
cairo_rectangle_int_t area;
PangoFont *font;
PangoGlyphInfo glyph_info;
float scale;
GskVulkanBuffer *buffer;
};
static void
gsk_vulkan_upload_glyph_op_finish (GskVulkanOp *op)
{
GskVulkanUploadGlyphOp *self = (GskVulkanUploadGlyphOp *) op;
g_object_unref (self->image);
g_object_unref (self->font);
g_clear_pointer (&self->buffer, gsk_vulkan_buffer_free);
}
static void
gsk_vulkan_upload_glyph_op_print (GskVulkanOp *op,
GString *string,
guint indent)
{
GskVulkanUploadGlyphOp *self = (GskVulkanUploadGlyphOp *) op;
print_indent (string, indent);
g_string_append (string, "upload-glyph ");
print_int_rect (string, &self->area);
g_string_append_printf (string, "glyph %u @ %g ", self->glyph_info.glyph, self->scale);
print_newline (string);
}
static void
gsk_vulkan_upload_glyph_op_draw (GskVulkanOp *op,
guchar *data,
gsize stride)
{
GskVulkanUploadGlyphOp *self = (GskVulkanUploadGlyphOp *) op;
cairo_surface_t *surface;
cairo_t *cr;
surface = cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_ARGB32,
self->area.width,
self->area.height,
stride);
cairo_surface_set_device_scale (surface, self->scale, self->scale);
cr = cairo_create (surface);
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
cairo_paint (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
/* Make sure the entire surface is initialized to black */
cairo_set_source_rgba (cr, 0, 0, 0, 0);
cairo_rectangle (cr, 0.0, 0.0, self->area.width, self->area.height);
cairo_fill (cr);
/* Draw glyph */
cairo_set_source_rgba (cr, 1, 1, 1, 1);
pango_cairo_show_glyph_string (cr,
self->font,
&(PangoGlyphString) {
.num_glyphs = 1,
.glyphs = &self->glyph_info
});
cairo_destroy (cr);
cairo_surface_finish (surface);
cairo_surface_destroy (surface);
}
static GskVulkanOp *
gsk_vulkan_upload_glyph_op_command (GskVulkanOp *op,
GskVulkanRender *render,
VkRenderPass render_pass,
VkCommandBuffer command_buffer)
{
GskVulkanUploadGlyphOp *self = (GskVulkanUploadGlyphOp *) op;
return gsk_vulkan_upload_op_command_with_area (op,
render,
command_buffer,
self->image,
&self->area,
gsk_vulkan_upload_glyph_op_draw,
&self->buffer);
}
static const GskVulkanOpClass GSK_VULKAN_UPLOAD_GLYPH_OP_CLASS = {
GSK_VULKAN_OP_SIZE (GskVulkanUploadGlyphOp),
GSK_VULKAN_STAGE_UPLOAD,
gsk_vulkan_upload_glyph_op_finish,
gsk_vulkan_upload_glyph_op_print,
gsk_vulkan_upload_op_count_vertex_data,
gsk_vulkan_upload_op_collect_vertex_data,
gsk_vulkan_upload_op_reserve_descriptor_sets,
gsk_vulkan_upload_glyph_op_command
};
void
gsk_vulkan_upload_glyph_op (GskVulkanRender *render,
GskVulkanImage *image,
cairo_rectangle_int_t *area,
PangoFont *font,
PangoGlyphInfo *glyph_info,
float scale)
{
GskVulkanUploadGlyphOp *self;
self = (GskVulkanUploadGlyphOp *) gsk_vulkan_op_alloc (render, &GSK_VULKAN_UPLOAD_GLYPH_OP_CLASS);
self->image = g_object_ref (image);
self->area = *area;
self->font = g_object_ref (font);
self->glyph_info = *glyph_info;
self->scale = scale;
}

View File

@ -1,23 +0,0 @@
#pragma once
#include "gskvulkanopprivate.h"
G_BEGIN_DECLS
GskVulkanImage * gsk_vulkan_upload_texture_op (GskVulkanRender *render,
GdkTexture *texture);
GskVulkanImage * gsk_vulkan_upload_cairo_op (GskVulkanRender *render,
GskRenderNode *node,
const graphene_vec2_t *scale,
const graphene_rect_t *viewport);
void gsk_vulkan_upload_glyph_op (GskVulkanRender *render,
GskVulkanImage *image,
cairo_rectangle_int_t *area,
PangoFont *font,
PangoGlyphInfo *glyph_info,
float scale);
G_END_DECLS

View File

@ -1,319 +0,0 @@
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"
#include "rect.frag.glsl"
layout(location = 0) in vec2 inPos;
layout(location = 1) in Rect inTopRect;
layout(location = 2) in Rect inBottomRect;
layout(location = 3) in vec2 inTopTexCoord;
layout(location = 4) in vec2 inBottomTexCoord;
layout(location = 5) flat in uint inTopTexId;
layout(location = 6) flat in uint inBottomTexId;
layout(location = 7) flat in uint inBlendMode;
layout(location = 0) out vec4 color;
float
combine (float source, float backdrop)
{
return source + backdrop * (1 - source);
}
vec4
composite (vec4 Cs, vec4 Cb, vec3 B)
{
float ao = Cs.a + Cb.a * (1 - Cs.a);
vec3 Co = (Cs.a*(1 - Cb.a)*Cs.rgb + Cs.a*Cb.a*B + (1 - Cs.a)*Cb.a*Cb.rgb) / ao;
return vec4(Co, ao);
}
vec4
normal (vec4 Cs, vec4 Cb)
{
return composite (Cs, Cb, Cs.rgb);
}
vec4
multiply (vec4 Cs, vec4 Cb)
{
return composite (Cs, Cb, Cs.rgb * Cb.rgb);
}
vec4
difference (vec4 Cs, vec4 Cb)
{
return composite (Cs, Cb, abs(Cs.rgb - Cb.rgb));
}
vec4
screen (vec4 Cs, vec4 Cb)
{
return composite (Cs, Cb, Cs.rgb + Cb.rgb - Cs.rgb * Cb.rgb);
}
float
hard_light (float source, float backdrop)
{
if (source <= 0.5)
return 2 * backdrop * source;
else
return 2 * (backdrop + source - backdrop * source) - 1;
}
vec4
hard_light (vec4 Cs, vec4 Cb)
{
vec3 B = vec3 (hard_light (Cs.r, Cb.r),
hard_light (Cs.g, Cb.g),
hard_light (Cs.b, Cb.b));
return composite (Cs, Cb, B);
}
float
soft_light (float source, float backdrop)
{
float db;
if (backdrop <= 0.25)
db = ((16 * backdrop - 12) * backdrop + 4) * backdrop;
else
db = sqrt (backdrop);
if (source <= 0.5)
return backdrop - (1 - 2 * source) * backdrop * (1 - backdrop);
else
return backdrop + (2 * source - 1) * (db - backdrop);
}
vec4
soft_light (vec4 Cs, vec4 Cb)
{
vec3 B = vec3 (soft_light (Cs.r, Cb.r),
soft_light (Cs.g, Cb.g),
soft_light (Cs.b, Cb.b));
return composite (Cs, Cb, B);
}
vec4
overlay (vec4 Cs, vec4 Cb)
{
vec3 B = vec3 (hard_light (Cb.r, Cs.r),
hard_light (Cb.g, Cs.g),
hard_light (Cb.b, Cs.b));
return composite (Cs, Cb, B);
}
vec4
darken (vec4 Cs, vec4 Cb)
{
vec3 B = min (Cs.rgb, Cb.rgb);
return composite (Cs, Cb, B);
}
vec4
lighten (vec4 Cs, vec4 Cb)
{
vec3 B = max (Cs.rgb, Cb.rgb);
return composite (Cs, Cb, B);
}
float
color_dodge (float source, float backdrop)
{
return (source == 1.0) ? source : min (backdrop / (1.0 - source), 1.0);
}
vec4
color_dodge (vec4 Cs, vec4 Cb)
{
vec3 B = vec3 (color_dodge (Cs.r, Cb.r),
color_dodge (Cs.g, Cb.g),
color_dodge (Cs.b, Cb.b));
return composite (Cs, Cb, B);
}
float
color_burn (float source, float backdrop)
{
return (source == 0.0) ? source : max ((1.0 - ((1.0 - backdrop) / source)), 0.0);
}
vec4
color_burn (vec4 Cs, vec4 Cb)
{
vec3 B = vec3 (color_burn (Cs.r, Cb.r),
color_burn (Cs.g, Cb.g),
color_burn (Cs.b, Cb.b));
return composite (Cs, Cb, B);
}
vec4
exclusion (vec4 Cs, vec4 Cb)
{
vec3 B = Cb.rgb + Cs.rgb - 2.0 * Cb.rgb * Cs.rgb;
return composite (Cs, Cb, B);
}
float
lum (vec3 c)
{
return 0.3 * c.r + 0.59 * c.g + 0.11 * c.b;
}
vec3
clip_color (vec3 c)
{
float l = lum (c);
float n = min (c.r, min (c.g, c.b));
float x = max (c.r, max (c.g, c.b));
if (n < 0) c = l + (((c - l) * l) / (l - n));
if (x > 1) c = l + (((c - l) * (1 - l)) / (x - l));
return c;
}
vec3
set_lum (vec3 c, float l)
{
float d = l - lum (c);
return clip_color (vec3 (c.r + d, c.g + d, c.b + d));
}
float
sat (vec3 c)
{
return max (c.r, max (c.g, c.b)) - min (c.r, min (c.g, c.b));
}
vec3
set_sat (vec3 c, float s)
{
float cmin = min (c.r, min (c.g, c.b));
float cmax = max (c.r, max (c.g, c.b));
vec3 res;
if (cmax == cmin)
res = vec3 (0, 0, 0);
else
{
if (c.r == cmax)
{
if (c.g == cmin)
{
res.b = ((c.b - cmin) * s) / (cmax - cmin);
res.g = 0;
}
else
{
res.g = ((c.g - cmin) * s) / (cmax - cmin);
res.b = 0;
}
res.r = s;
}
else if (c.g == cmax)
{
if (c.r == cmin)
{
res.b = ((c.b - cmin) * s) / (cmax - cmin);
res.r = 0;
}
else
{
res.r = ((c.r - cmin) * s) / (cmax - cmin);
res.b = 0;
}
res.g = s;
}
else
{
if (c.r == cmin)
{
res.g = ((c.g - cmin) * s) / (cmax - cmin);
res.r = 0;
}
else
{
res.r = ((c.r - cmin) * s) / (cmax - cmin);
res.g = 0;
}
res.b = s;
}
}
return res;
}
vec4
colorize (vec4 Cs, vec4 Cb)
{
vec3 B = set_lum (Cs.rgb, lum (Cb.rgb));
return composite (Cs, Cb, B);
}
vec4
hue (vec4 Cs, vec4 Cb)
{
vec3 B = set_lum (set_sat (Cs.rgb, sat (Cb.rgb)), lum (Cb.rgb));
return composite (Cs, Cb, B);
}
vec4
saturation (vec4 Cs, vec4 Cb)
{
vec3 B = set_lum (set_sat (Cb.rgb, sat (Cs.rgb)), lum (Cb.rgb));
return composite (Cs, Cb, B);
}
vec4
luminosity (vec4 Cs, vec4 Cb)
{
vec3 B = set_lum (Cb.rgb, lum (Cs.rgb));
return composite (Cs, Cb, B);
}
void main()
{
float source_alpha = rect_coverage (inTopRect, inPos);
vec4 source = texture (get_sampler (inTopTexId), inTopTexCoord) * source_alpha;
float backdrop_alpha = rect_coverage (inBottomRect, inPos);
vec4 backdrop = texture (get_sampler (inBottomTexId), inBottomTexCoord) * backdrop_alpha;
vec4 result;
if (inBlendMode == 0)
result = normal (source, backdrop);
else if (inBlendMode == 1)
result = multiply (source, backdrop);
else if (inBlendMode == 2)
result = screen (source, backdrop);
else if (inBlendMode == 3)
result = overlay (source, backdrop);
else if (inBlendMode == 4)
result = darken (source, backdrop);
else if (inBlendMode == 5)
result = lighten (source, backdrop);
else if (inBlendMode == 6)
result = color_dodge (source, backdrop);
else if (inBlendMode == 7)
result = color_burn (source, backdrop);
else if (inBlendMode == 8)
result = hard_light (source, backdrop);
else if (inBlendMode == 9)
result = soft_light (source, backdrop);
else if (inBlendMode == 10)
result = difference (source, backdrop);
else if (inBlendMode == 11)
result = exclusion (source, backdrop);
else if (inBlendMode == 12)
result = colorize (source, backdrop);
else if (inBlendMode == 13)
result = hue (source, backdrop);
else if (inBlendMode == 14)
result = saturation (source, backdrop);
else if (inBlendMode == 15)
result = luminosity (source, backdrop);
else
discard;
color = clip_scaled (inPos, result);
}

View File

@ -1,36 +0,0 @@
#version 450
#include "common.vert.glsl"
#include "rect.vert.glsl"
layout(location = 0) in vec4 inRect;
layout(location = 1) in vec4 inTopRect;
layout(location = 2) in vec4 inBottomRect;
layout(location = 3) in vec4 inTopTexRect;
layout(location = 4) in vec4 inBottomTexRect;
layout(location = 5) in uint inTopTexId;
layout(location = 6) in uint inBottomTexId;
layout(location = 7) in uint inBlendMode;
layout(location = 0) out vec2 outPos;
layout(location = 1) flat out Rect outTopRect;
layout(location = 2) flat out Rect outBottomRect;
layout(location = 3) out vec2 outTopTexCoord;
layout(location = 4) out vec2 outBottomTexCoord;
layout(location = 5) flat out uint outTopTexId;
layout(location = 6) flat out uint outBottomTexId;
layout(location = 7) flat out uint outBlendMode;
void main() {
Rect r = rect_from_gsk (inRect);
vec2 pos = set_position_from_rect (r);
outPos = pos;
outTopRect = rect_from_gsk (inTopRect);
outBottomRect = rect_from_gsk (inBottomRect);
outTopTexCoord = scale_tex_coord (pos, r, inTopTexRect);
outBottomTexCoord = scale_tex_coord (pos, r, inBottomTexRect);
outTopTexId = inTopTexId;
outBottomTexId = inBottomTexId;
outBlendMode = inBlendMode;
}

View File

@ -1,50 +0,0 @@
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"
layout(location = 0) in vec2 inPos;
layout(location = 1) in flat vec2 inSize;
layout(location = 2) in vec2 inTexCoord;
layout(location = 3) in float inRadius;
layout(location = 4) in flat uint inTexId;
layout(location = 0) out vec4 color;
const int samples_x = 15; // must be odd
const int samples_y = 15; // must be odd
const int half_samples_x = samples_x / 2;
const int half_samples_y = samples_y / 2;
float Gaussian (float sigma, float x)
{
return exp ( - (x * x) / (2.0 * sigma * sigma));
}
vec4 blur_pixel (in vec2 uv)
{
float total = 0.0;
vec4 ret = vec4 (0);
float pixel_size_x = (1.0 / inSize.x);
float pixel_size_y = (1.0 / inSize.y);
for (int y = 0; y < samples_y; ++y)
{
float fy = Gaussian (inRadius, float(y) - float(half_samples_x));
float offset_y = float(y - half_samples_y) * pixel_size_y;
for (int x = 0; x < samples_x; ++x)
{
float fx = Gaussian (inRadius, float(x) - float(half_samples_x));
float offset_x = float(x - half_samples_x) * pixel_size_x;
total += fx * fy;
ret += texture(get_sampler (inTexId), uv + vec2(offset_x, offset_y)) * fx * fy;
}
}
return ret / total;
}
void main()
{
color = clip (inPos, blur_pixel (inTexCoord));
}

View File

@ -1,39 +0,0 @@
#version 450
#include "clip.vert.glsl"
layout(location = 0) in vec4 inRect;
layout(location = 1) in vec4 inTexRect;
layout(location = 2) in float inRadius;
layout(location = 3) in uint inTexId;
layout(location = 0) out vec2 outPos;
layout(location = 1) out flat vec2 outSize;
layout(location = 2) out vec2 outTexCoord;
layout(location = 3) out flat float outRadius;
layout(location = 4) out flat uint outTexId;
vec2 offsets[6] = { vec2(0.0, 0.0),
vec2(1.0, 0.0),
vec2(0.0, 1.0),
vec2(0.0, 1.0),
vec2(1.0, 0.0),
vec2(1.0, 1.0) };
void main() {
vec4 rect = clip (inRect);
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
outPos = pos;
outSize = inRect.zw;
vec4 texrect = vec4((rect.xy - inRect.xy) / inRect.zw,
rect.zw / inRect.zw);
texrect = vec4(inTexRect.xy + inTexRect.zw * texrect.xy,
inTexRect.zw * texrect.zw);
outTexCoord = texrect.xy + texrect.zw * offsets[gl_VertexIndex];
outTexId = inTexId;
outRadius = inRadius;
}

View File

@ -1,22 +0,0 @@
#version 450
#include "clip.frag.glsl"
#include "rounded-rect.glsl"
layout(location = 0) in vec2 inPos;
layout(location = 1) in vec4 inColor;
layout(location = 2) in RoundedRect inRect;
layout(location = 5) in vec4 inBorderWidths;
layout(location = 0) out vec4 color;
void main()
{
RoundedRect routside = inRect;
RoundedRect rinside = rounded_rect_shrink (routside, inBorderWidths);
float alpha = clamp (rounded_rect_coverage (routside, inPos) -
rounded_rect_coverage (rinside, inPos),
0.0, 1.0);
color = clip_scaled (inPos, vec4(inColor.rgb * inColor.a, inColor.a) * alpha);
}

View File

@ -1,103 +0,0 @@
#version 450
#include "clip.vert.glsl"
#include "rounded-rect.glsl"
layout(location = 0) in mat3x4 inRect;
layout(location = 3) in vec4 inBorderWidths;
layout(location = 4) in mat4 inBorderColors;
layout(location = 0) out vec2 outPos;
layout(location = 1) out flat vec4 outColor;
layout(location = 2) out flat RoundedRect outRect;
layout(location = 5) out flat vec4 outBorderWidths;
vec2 offsets[6] = { vec2(0.0, 0.0),
vec2(1.0, 0.0),
vec2(0.0, 1.0),
vec2(1.0, 1.0),
vec2(0.0, 1.0),
vec2(1.0, 0.0) };
#define TOP 0
#define RIGHT 1
#define BOTTOM 2
#define LEFT 3
#define TOP_LEFT 0
#define TOP_RIGHT 1
#define BOTTOM_RIGHT 2
#define BOTTOM_LEFT 3
#define SLICE_TOP_LEFT 0
#define SLICE_TOP 1
#define SLICE_TOP_RIGHT 2
#define SLICE_RIGHT 3
#define SLICE_BOTTOM_RIGHT 4
#define SLICE_BOTTOM 5
#define SLICE_BOTTOM_LEFT 6
#define SLICE_LEFT 7
void main() {
int slice_index = gl_VertexIndex / 6;
int vert_index = gl_VertexIndex % 6;
vec4 corner_widths = max (inRect[1], inBorderWidths.wyyw);
vec4 corner_heights = max (inRect[2], inBorderWidths.xxzz);
Rect rect;
switch (slice_index)
{
case SLICE_TOP_LEFT:
rect = rect_from_gsk (vec4(inRect[0].xy, corner_widths[TOP_LEFT], corner_heights[TOP_LEFT]));
rect = rect_round_larger (rect);
vert_index = (vert_index + 3) % 6;
break;
case SLICE_TOP:
rect = rect_from_gsk (vec4(inRect[0].x + corner_widths[TOP_LEFT], inRect[0].y, inRect[0].z - corner_widths[TOP_LEFT] - corner_widths[TOP_RIGHT], inBorderWidths[TOP]));
rect = rect_round_smaller_larger (rect);
outColor = inBorderColors[TOP];
break;
case SLICE_TOP_RIGHT:
rect = rect_from_gsk (vec4(inRect[0].x + inRect[0].z - corner_widths[TOP_RIGHT], inRect[0].y, corner_widths[TOP_RIGHT], corner_heights[TOP_RIGHT]));
rect = rect_round_larger (rect);
break;
case SLICE_RIGHT:
rect = rect_from_gsk (vec4(inRect[0].x + inRect[0].z - inBorderWidths[RIGHT], inRect[0].y + corner_heights[TOP_RIGHT], inBorderWidths[RIGHT], inRect[0].w - corner_heights[TOP_RIGHT] - corner_heights[BOTTOM_RIGHT]));
rect = rect_round_larger_smaller (rect);
outColor = inBorderColors[RIGHT];
break;
case SLICE_BOTTOM_RIGHT:
rect = rect_from_gsk (vec4(inRect[0].x + inRect[0].z - corner_widths[BOTTOM_RIGHT], inRect[0].y + inRect[0].w - corner_heights[BOTTOM_RIGHT], corner_widths[BOTTOM_RIGHT], corner_heights[BOTTOM_RIGHT]));
rect = rect_round_larger (rect);
break;
case SLICE_BOTTOM:
rect = rect_from_gsk (vec4(inRect[0].x + corner_widths[BOTTOM_LEFT], inRect[0].y + inRect[0].w - inBorderWidths[BOTTOM], inRect[0].z - corner_widths[BOTTOM_LEFT] - corner_widths[BOTTOM_RIGHT], inBorderWidths[BOTTOM]));
rect = rect_round_smaller_larger (rect);
break;
case SLICE_BOTTOM_LEFT:
rect = rect_from_gsk (vec4(inRect[0].x, inRect[0].y + inRect[0].w - corner_heights[BOTTOM_LEFT], corner_widths[BOTTOM_LEFT], corner_heights[BOTTOM_LEFT]));
vert_index = (vert_index + 3) % 6;
rect = rect_round_larger (rect);
break;
case SLICE_LEFT:
rect = rect_from_gsk (vec4(inRect[0].x, inRect[0].y + corner_heights[TOP_LEFT], inBorderWidths[LEFT], inRect[0].w - corner_heights[TOP_LEFT] - corner_heights[BOTTOM_LEFT]));
rect = rect_round_larger_smaller (rect);
break;
}
rect = clip_rect (rect);
vec2 pos;
if ((slice_index % 4) != 0 || (vert_index % 3) != 2)
pos = mix (rect.bounds.xy, rect.bounds.zw, offsets[vert_index]);
else
pos = mix (rect.bounds.zy, rect.bounds.xw, offsets[vert_index]);
gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
outColor = inBorderColors[((gl_VertexIndex / 3 + 15) / 4) % 4];
outPos = pos;
outRect = RoundedRect(inRect[0].xyxy + vec4(0,0,inRect[0].zw), inRect[1], inRect[2]);
outRect = rounded_rect_scale (outRect, push.scale);
outBorderWidths = inBorderWidths * push.scale.yxyx;
}

View File

@ -1,45 +0,0 @@
#include "constants.glsl"
#include "rounded-rect.frag.glsl"
#ifndef _CLIP_
#define _CLIP_
#ifdef CLIP_ROUNDED_RECT
vec4
clip_scaled (vec2 pos, vec4 color)
{
RoundedRect r = RoundedRect(vec4(push.clip_bounds.xy, push.clip_bounds.xy + push.clip_bounds.zw), push.clip_widths, push.clip_heights);
r = rounded_rect_scale (r, push.scale);
return color * rounded_rect_coverage (r, pos);
}
#elif defined(CLIP_RECT)
vec4
clip_scaled (vec2 pos, vec4 color)
{
return color;
}
#elif defined(CLIP_NONE)
vec4
clip_scaled (vec2 pos, vec4 color)
{
return color;
}
#else
#error "No clipping define given. Need CLIP_NONE, CLIP_RECT or CLIP_ROUNDED_RECT"
#endif
vec4
clip (vec2 pos, vec4 color)
{
return clip_scaled (pos * push.scale, color);
}
#endif

View File

@ -1,63 +0,0 @@
#include "constants.glsl"
#include "rect.vert.glsl"
#ifndef _CLIP_
#define _CLIP_
vec4 intersect(vec4 a, vec4 b)
{
a = vec4(a.xy, a.xy + a.zw);
b = vec4(b.xy, b.xy + b.zw);
vec4 result = vec4(max(a.xy, b.xy), min(a.zw, b.zw));
if (any (greaterThanEqual (result.xy, result.zw)))
return vec4(0.0,0.0,0.0,0.0);
return vec4(result.xy, result.zw - result.xy);
}
#ifdef CLIP_ROUNDED_RECT
vec4
clip(vec4 rect)
{
/* rounded corner clipping is done in fragment shader */
return intersect(rect, push.clip_bounds);
}
Rect
clip_rect (Rect r)
{
/* rounded corner clipping is done in fragment shader */
return rect_intersect (r, rect_round_larger (rect_from_gsk (push.clip_bounds)));
}
#elif defined(CLIP_RECT)
vec4
clip(vec4 rect)
{
return intersect(rect, push.clip_bounds);
}
Rect
clip_rect (Rect r)
{
return rect_intersect (r, rect_round_larger (rect_from_gsk (push.clip_bounds)));
}
#elif defined(CLIP_NONE)
vec4 clip(vec4 rect)
{
return rect;
}
Rect
clip_rect (Rect r)
{
return r;
}
#else
#error "No clipping define given. Need CLIP_NONE, CLIP_RECT or CLIP_ROUNDED_RECT"
#endif
#endif

View File

@ -1,33 +0,0 @@
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"
layout(location = 0) in vec2 inPos;
layout(location = 1) in vec2 inTexCoord;
layout(location = 2) in flat mat4 inColorMatrix;
layout(location = 6) in flat vec4 inColorOffset;
layout(location = 7) in flat uint inTexId;
layout(location = 0) out vec4 color;
vec4
color_matrix (vec4 color, mat4 color_matrix, vec4 color_offset)
{
/* unpremultiply */
if (color.a != 0.0)
color.rgb /= color.a;
color = color_matrix * color + color_offset;
color = clamp(color, 0.0, 1.0);
/* premultiply */
color.rgb *= color.a;
return color;
}
void main()
{
color = clip (inPos, color_matrix (texture (get_sampler (inTexId), inTexCoord), inColorMatrix, inColorOffset));
}

View File

@ -1,39 +0,0 @@
#version 450
#include "clip.vert.glsl"
layout(location = 0) in vec4 inRect;
layout(location = 1) in vec4 inTexRect;
layout(location = 2) in mat4 inColorMatrix;
layout(location = 6) in vec4 inColorOffset;
layout(location = 7) in uint inTexId;
layout(location = 0) out vec2 outPos;
layout(location = 1) out vec2 outTexCoord;
layout(location = 2) out flat mat4 outColorMatrix;
layout(location = 6) out flat vec4 outColorOffset;
layout(location = 7) out flat uint outTexId;
vec2 offsets[6] = { vec2(0.0, 0.0),
vec2(1.0, 0.0),
vec2(0.0, 1.0),
vec2(0.0, 1.0),
vec2(1.0, 0.0),
vec2(1.0, 1.0) };
void main() {
vec4 rect = clip (inRect);
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
outPos = pos;
vec4 texrect = vec4((rect.xy - inRect.xy) / inRect.zw,
rect.zw / inRect.zw);
texrect = vec4(inTexRect.xy + inTexRect.zw * texrect.xy,
inTexRect.zw * texrect.zw);
outTexCoord = texrect.xy + texrect.zw * offsets[gl_VertexIndex];
outTexId = inTexId;
outColorMatrix = inColorMatrix;
outColorOffset = inColorOffset;
}

View File

@ -1,16 +0,0 @@
#version 420 core
#include "clip.frag.glsl"
#include "rect.frag.glsl"
layout(location = 0) in vec2 inPos;
layout(location = 1) in Rect inRect;
layout(location = 2) in vec4 inColor;
layout(location = 0) out vec4 color;
void main()
{
float alpha = inColor.a * rect_coverage (inRect, inPos);
color = clip_scaled (inPos, vec4(inColor.rgb, 1) * alpha);
}

View File

@ -1,18 +0,0 @@
#version 450
#include "common.vert.glsl"
#include "rect.vert.glsl"
layout(location = 0) in vec4 inRect;
layout(location = 1) in vec4 inColor;
layout(location = 0) out vec2 outPos;
layout(location = 1) out flat Rect outRect;
layout(location = 2) out flat vec4 outColor;
void main() {
Rect r = rect_from_gsk (inRect);
outPos = set_position_from_rect (r);
outRect = r;
outColor = inColor;
}

View File

@ -1,11 +0,0 @@
#extension GL_EXT_nonuniform_qualifier : enable
layout(set = 0, binding = 0) uniform sampler2D textures[50000];
layout(set = 1, binding = 0) readonly buffer FloatBuffers {
float floats[];
} buffers[50000];
#define get_sampler(id) textures[nonuniformEXT (id)]
#define get_buffer(id) buffers[nonuniformEXT (id)]
#define get_float(id) get_buffer(0).floats[nonuniformEXT (id)]

View File

@ -1,34 +0,0 @@
#ifndef _COMMON_VERT_
#define _COMMON_VERT_
#include "clip.vert.glsl"
#include "constants.glsl"
#include "rect.glsl"
vec2 offsets[6] = { vec2(0.0, 0.0),
vec2(1.0, 0.0),
vec2(0.0, 1.0),
vec2(0.0, 1.0),
vec2(1.0, 0.0),
vec2(1.0, 1.0) };
vec2
set_position_from_rect (Rect rect)
{
Rect r = rect_round_larger (clip_rect (rect));
vec2 pos = mix (r.bounds.xy, r.bounds.zw, offsets[gl_VertexIndex]);
gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
return pos;
}
vec2
scale_tex_coord (vec2 in_pos,
Rect in_rect,
vec4 tex_rect)
{
return tex_rect.xy + (in_pos - in_rect.bounds.xy) / rect_size (in_rect) * tex_rect.zw;
}
#endif

View File

@ -1,12 +0,0 @@
#ifndef _CONSTANTS_
#define _CONSTANTS_
layout(push_constant) uniform PushConstants {
mat4 mvp;
vec4 clip_bounds;
vec4 clip_widths;
vec4 clip_heights;
vec2 scale;
} push;
#endif

View File

@ -1,29 +0,0 @@
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"
#include "rect.frag.glsl"
#define GSK_VULKAN_IMAGE_PREMULTIPLY (1 << 0)
#
layout(location = 0) in vec2 in_pos;
layout(location = 1) in Rect in_rect;
layout(location = 2) in vec2 in_tex_coord;
layout(location = 3) flat in uint in_tex_id;
layout(location = 4) in flat uint in_postprocess;
layout(location = 0) out vec4 color;
void main()
{
float alpha = rect_coverage (in_rect, in_pos);
/* warning: This breaks with filters other than nearest,
as linear filtering needs premultiplied alpha */
vec4 pixel = texture (get_sampler (in_tex_id), in_tex_coord);
if ((in_postprocess & GSK_VULKAN_IMAGE_PREMULTIPLY) != 0)
pixel.rgb *= pixel.a;
color = clip_scaled (in_pos, pixel * alpha);
}

View File

@ -1,26 +0,0 @@
#version 450
#include "common.vert.glsl"
#include "rect.vert.glsl"
layout(location = 0) in vec4 in_rect;
layout(location = 1) in vec4 in_tex_rect;
layout(location = 2) in uint in_tex_id;
layout(location = 3) in uint in_postprocess;
layout(location = 0) out vec2 out_pos;
layout(location = 1) out flat Rect out_rect;
layout(location = 2) out vec2 out_tex_coord;
layout(location = 3) out flat uint out_tex_id;
layout(location = 4) out flat uint out_postprocess;
void main() {
Rect r = rect_from_gsk (in_rect);
vec2 pos = set_position_from_rect (r);
out_pos = pos;
out_rect = r;
out_tex_coord = scale_tex_coord (pos, r, in_tex_rect);
out_tex_id = in_tex_id;
out_postprocess = in_postprocess;
}

View File

@ -1,26 +0,0 @@
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"
#include "rect.frag.glsl"
layout(location = 0) in vec2 inPos;
layout(location = 1) in Rect inStartRect;
layout(location = 2) in Rect inEndRect;
layout(location = 3) in vec2 inStartTexCoord;
layout(location = 4) in vec2 inEndTexCoord;
layout(location = 5) flat in uint inStartTexId;
layout(location = 6) flat in uint inEndTexId;
layout(location = 7) in float inProgress;
layout(location = 0) out vec4 color;
void main()
{
float start_alpha = rect_coverage (inStartRect, inPos);
vec4 start = texture (get_sampler (inStartTexId), inStartTexCoord) * start_alpha;
float end_alpha = rect_coverage (inEndRect, inPos);
vec4 end = texture (get_sampler (inEndTexId), inEndTexCoord) * end_alpha;
color = clip_scaled (inPos, mix (start, end, inProgress));
}

View File

@ -1,36 +0,0 @@
#version 450
#include "common.vert.glsl"
#include "rect.vert.glsl"
layout(location = 0) in vec4 inRect;
layout(location = 1) in vec4 inStartRect;
layout(location = 2) in vec4 inEndRect;
layout(location = 3) in vec4 inStartTexRect;
layout(location = 4) in vec4 inEndTexRect;
layout(location = 5) in uint inStartTexId;
layout(location = 6) in uint inEndTexId;
layout(location = 7) in float inProgress;
layout(location = 0) out vec2 outPos;
layout(location = 1) flat out Rect outStartRect;
layout(location = 2) flat out Rect outEndRect;
layout(location = 3) out vec2 outStartTexCoord;
layout(location = 4) out vec2 outEndTexCoord;
layout(location = 5) flat out uint outStartTexId;
layout(location = 6) flat out uint outEndTexId;
layout(location = 7) flat out float outProgress;
void main() {
Rect r = rect_from_gsk (inRect);
vec2 pos = set_position_from_rect (r);
outPos = pos;
outStartRect = rect_from_gsk (inStartRect);
outEndRect = rect_from_gsk (inEndRect);
outStartTexCoord = scale_tex_coord (pos, r, inStartTexRect);
outEndTexCoord = scale_tex_coord (pos, r, inEndTexRect);
outStartTexId = inStartTexId;
outEndTexId = inEndTexId;
outProgress = inProgress;
}

View File

@ -1,38 +0,0 @@
#ifndef _ELLIPSE_
#define _ELLIPSE_
struct Ellipse
{
vec2 center;
vec2 radius;
};
float
ellipse_distance (Ellipse r, vec2 p)
{
vec2 e = r.radius;
p = p - r.center;
if (e.x == e.y)
return length (p) - e.x;
/* from https://www.shadertoy.com/view/tt3yz7 */
vec2 pAbs = abs(p);
vec2 ei = 1.0 / e;
vec2 e2 = e*e;
vec2 ve = ei * vec2(e2.x - e2.y, e2.y - e2.x);
vec2 t = vec2(0.70710678118654752, 0.70710678118654752);
for (int i = 0; i < 3; i++) {
vec2 v = ve*t*t*t;
vec2 u = normalize(pAbs - v) * length(t * e - v);
vec2 w = ei * (v + u);
t = normalize(clamp(w, 0.0, 1.0));
}
vec2 nearestAbs = t * e;
float dist = length(pAbs - nearestAbs);
return dot(pAbs, pAbs) < dot(nearestAbs, nearestAbs) ? -dist : dist;
}
#endif

View File

@ -1,174 +0,0 @@
#!/usr/bin/env python3
import sys
import re
import os
name = os.path.splitext(os.path.basename(sys.argv[1]))[0]
var_name = "gsk_vulkan_" + name.replace('-', '_')
struct_name = "GskVulkan" + name.title().replace('-', '') + "Instance"
with open(sys.argv[1]) as f:
lines = f.readlines()
matches = []
for line in lines:
match = re.search(r"^layout\(location = ([0-9]+)\) in ([a-z0-9]+) ([a-zA-Z0-9_]+);$", line)
if not match:
if re.search(r"layout.*\sin\s.*", line):
raise Exception("Failed to parse file")
continue
if not match.group(3).startswith('in'):
raise Exception("Variable doesn't start with 'in'")
matches.append({'name': ''.join('_' + char.lower() if char.isupper() else char for char in match.group(3))[3:],
'location': int(match.group(1)),
'type': match.group(2)})
print(f'''/* This file is auto-generated; any change will not be preserved */
#pragma once
typedef struct _{struct_name} {struct_name};
struct _{struct_name} {{''')
expected = 0
for match in matches:
if expected != int(match['location']):
raise Exception(f"Should be layout location {expected} but is {match['location']}") # noqa
if match['type'] == 'float':
print(f" float {match['name']};")
expected += 1
elif match['type'] == 'int':
print(f" gint32 {match['name']};")
expected += 1
elif match['type'] == 'uint':
print(f" guint32 {match['name']};")
expected += 1
elif match['type'] == 'uvec2':
print(f" guint32 {match['name']}[2];")
expected += 1
elif match['type'] == 'vec2':
print(f" float {match['name']}[2];")
expected += 1
elif match['type'] == 'vec4':
print(f" float {match['name']}[4];")
expected += 1
elif match['type'] == 'mat3x4':
print(f" float {match['name']}[12];")
expected += 3
elif match['type'] == 'mat4':
print(f" float {match['name']}[16];")
expected += 4
else:
raise Exception(f"Don't know what a {match['type']} is")
print('''};
''')
print(f'''static const VkPipelineVertexInputStateCreateInfo {var_name}_info = {{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.vertexBindingDescriptionCount = 1,
.pVertexBindingDescriptions = (VkVertexInputBindingDescription[1]) {{
{{
.binding = 0,
.stride = sizeof ({struct_name}),
.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE
}}
}},
.vertexAttributeDescriptionCount = {expected},
.pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[{expected}]) {{''')
for match in matches:
if match['type'] == 'float':
print(f''' {{
.location = {match['location']},
.binding = 0,
.format = VK_FORMAT_R32_SFLOAT,
.offset = G_STRUCT_OFFSET({struct_name}, {match['name']}),
}},''')
elif match['type'] == 'int':
print(f''' {{
.location = {match['location']},
.binding = 0,
.format = VK_FORMAT_R32_SINT,
.offset = G_STRUCT_OFFSET({struct_name}, {match['name']}),
}},''')
elif match['type'] == 'uint':
print(f''' {{
.location = {match['location']},
.binding = 0,
.format = VK_FORMAT_R32_UINT,
.offset = G_STRUCT_OFFSET({struct_name}, {match['name']}),
}},''')
elif match['type'] == 'uvec2':
print(f''' {{
.location = {match['location']},
.binding = 0,
.format = VK_FORMAT_R32G32_UINT,
.offset = G_STRUCT_OFFSET({struct_name}, {match['name']}),
}},''')
elif match['type'] == 'vec2':
print(f''' {{
.location = {match['location']},
.binding = 0,
.format = VK_FORMAT_R32G32_SFLOAT,
.offset = G_STRUCT_OFFSET({struct_name}, {match['name']}),
}},''')
elif match['type'] == 'vec4':
print(f''' {{
.location = {match['location']},
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET({struct_name}, {match['name']}),
}},''')
elif match['type'] == 'mat3x4':
print(f''' {{
.location = {match['location']},
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET({struct_name}, {match['name']}),
}},
{{
.location = {int(match['location']) + 1},
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET({struct_name}, {match['name']}) + sizeof (float) * 4,
}},
{{
.location = {int(match['location']) + 2},
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET({struct_name}, {match['name']}) + sizeof (float) * 8,
}},''')
elif match['type'] == 'mat4':
print(f''' {{
.location = {match['location']},
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET({struct_name}, {match['name']}),
}},
{{
.location = {int(match['location']) + 1},
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET({struct_name}, {match['name']}) + sizeof (float) * 4,
}},
{{
.location = {int(match['location']) + 2},
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET({struct_name}, {match['name']}) + sizeof (float) * 8,
}},
{{
.location = {int(match['location']) + 3},
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = G_STRUCT_OFFSET({struct_name}, {match['name']}) + sizeof (float) * 12,
}},''')
else:
raise Exception(f"Don't know what a {match['type']} is")
print(" },")
print("};")

View File

@ -1,20 +0,0 @@
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"
#include "rect.frag.glsl"
layout(location = 0) in vec2 inPos;
layout(location = 1) in flat Rect inRect;
layout(location = 2) in vec2 inTexCoord;
layout(location = 3) in flat uint inTexId;
layout(location = 4) in flat vec4 inColor;
layout(location = 0) out vec4 color;
void main()
{
float alpha = inColor.a * rect_coverage (inRect, inPos);
alpha *= texture(get_sampler (inTexId), inTexCoord).a;
color = clip_scaled (inPos, vec4(inColor.rgb, 1) * alpha);
}

View File

@ -1,26 +0,0 @@
#version 450
#include "common.vert.glsl"
#include "rect.vert.glsl"
layout(location = 0) in vec4 inRect;
layout(location = 1) in vec4 inTexRect;
layout(location = 2) in vec4 inColor;
layout(location = 3) in uint inTexId;
layout(location = 0) out vec2 outPos;
layout(location = 1) out flat Rect outRect;
layout(location = 2) out vec2 outTexCoord;
layout(location = 3) out flat uint outTexId;
layout(location = 4) out flat vec4 outColor;
void main() {
Rect r = rect_from_gsk (inRect);
vec2 pos = set_position_from_rect (r);
outPos = pos;
outRect = r;
outTexCoord = scale_tex_coord (pos, r, inTexRect);
outTexId = inTexId;
outColor = inColor;
}

View File

@ -1,26 +0,0 @@
#version 450
#include "clip.frag.glsl"
#include "rounded-rect.glsl"
layout(location = 0) in vec2 inPos;
layout(location = 1) in flat vec4 inOutline;
layout(location = 2) in flat vec4 inOutlineCornerWidths;
layout(location = 3) in flat vec4 inOutlineCornerHeights;
layout(location = 4) in flat vec4 inColor;
layout(location = 5) in flat vec2 inOffset;
layout(location = 6) in flat float inSpread;
layout(location = 0) out vec4 color;
void main()
{
RoundedRect outline = RoundedRect (vec4(inOutline.xy, inOutline.xy + inOutline.zw), inOutlineCornerWidths, inOutlineCornerHeights);
RoundedRect inside = rounded_rect_shrink (outline, vec4(inSpread));
color = vec4(inColor.rgb * inColor.a, inColor.a);
color = color * clamp (rounded_rect_coverage (outline, inPos) -
rounded_rect_coverage (inside, inPos - inOffset),
0.0, 1.0);
color = clip (inPos, color);
}

View File

@ -1,39 +0,0 @@
#version 450
#include "clip.vert.glsl"
layout(location = 0) in mat3x4 inOutline;
layout(location = 3) in vec4 inColor;
layout(location = 4) in vec2 inOffset;
layout(location = 5) in float inSpread;
layout(location = 6) in float inBlurRadius;
layout(location = 0) out vec2 outPos;
layout(location = 1) out flat vec4 outOutline;
layout(location = 2) out flat vec4 outOutlineCornerWidths;
layout(location = 3) out flat vec4 outOutlineCornerHeights;
layout(location = 4) out flat vec4 outColor;
layout(location = 5) out flat vec2 outOffset;
layout(location = 6) out flat float outSpread;
vec2 offsets[6] = { vec2(0.0, 0.0),
vec2(1.0, 0.0),
vec2(0.0, 1.0),
vec2(0.0, 1.0),
vec2(1.0, 0.0),
vec2(1.0, 1.0) };
void main() {
vec4 rect = clip (inOutline[0]);
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
outPos = pos;
outOutline = inOutline[0];
outOutlineCornerWidths = inOutline[1];
outOutlineCornerHeights = inOutline[2];
outColor = inColor;
outOffset = inOffset;
outSpread = inSpread;
}

View File

@ -1,128 +0,0 @@
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"
#include "rect.frag.glsl"
layout(location = 0) in vec2 inPos;
layout(location = 1) in flat Rect inRect;
layout(location = 2) in float inGradientPos;
layout(location = 3) in flat int inRepeating;
layout(location = 4) in flat int inStopOffset;
layout(location = 5) in flat int inStopCount;
layout(location = 0) out vec4 color;
float
get_offset (int i)
{
return get_float (inStopOffset + i * 5);
}
vec4
get_color (int i)
{
i = clamp (i, 0, inStopCount - 1);
return color = vec4 (get_float (inStopOffset + i * 5 + 1),
get_float (inStopOffset + i * 5 + 2),
get_float (inStopOffset + i * 5 + 3),
get_float (inStopOffset + i * 5 + 4));
}
vec4
get_color_for_range_unscaled (float start,
float end)
{
vec4 result = vec4 (0);
float offset;
int i;
for (i = 0; i < inStopCount; i++)
{
offset = get_offset (i);
if (offset >= start)
break;
}
if (i == inStopCount)
offset = 1;
float last_offset = i > 0 ? get_offset (i - 1) : 0;
vec4 last_color = get_color (i - 1);
vec4 color = get_color (i);
if (last_offset < start)
{
last_color = mix (last_color, color, (start - last_offset) / (offset - last_offset));
last_offset = start;
}
if (end <= start)
return last_color;
for (; i < inStopCount; i++)
{
offset = get_offset (i);
color = get_color (i);
if (offset >= end)
break;
result += 0.5 * (color + last_color) * (offset - last_offset);
last_offset = offset;
last_color = color;
}
if (i == inStopCount)
{
offset = 1;
color = get_color (i);
}
if (offset > end)
{
color = mix (last_color, color, (end - last_offset) / (offset - last_offset));
offset = end;
}
result += 0.5 * (color + last_color) * (offset - last_offset);
return result;
}
vec4
get_color_for_range (float start,
float end)
{
return get_color_for_range_unscaled (start, end) / (end - start);
}
void main()
{
vec4 c;
float pos_start, pos_end;
float dPos = 0.5 * abs (fwidth (inGradientPos));
if (inRepeating != 0)
{
pos_start = inGradientPos - dPos;
pos_end = inGradientPos + dPos;
if (floor (pos_end) > floor (pos_start))
{
float fract_end = fract(pos_end);
float fract_start = fract(pos_start);
float n = floor (pos_end) - floor (pos_start);
if (fract_end > fract_start + 0.01)
c = get_color_for_range_unscaled (fract_start, fract_end);
else if (fract_start > fract_end + 0.01)
c = -get_color_for_range_unscaled (fract_end, fract_start);
c += get_color_for_range_unscaled (0.0, 1.0) * n;
c /= pos_end - pos_start;
}
else
{
c = get_color_for_range (fract (pos_start), fract (pos_end));
}
}
else
{
pos_start = clamp (inGradientPos - dPos, 0, 1);
pos_end = clamp (inGradientPos + dPos, 0, 1);
c = get_color_for_range (pos_start, pos_end);
}
float alpha = c.a * rect_coverage (inRect, inPos);
color = clip_scaled (inPos, vec4(c.rgb, 1) * alpha);
}

View File

@ -1,38 +0,0 @@
#version 450
#include "common.vert.glsl"
#include "rect.vert.glsl"
layout(location = 0) in vec4 inRect;
layout(location = 1) in vec2 inStart;
layout(location = 2) in vec2 inEnd;
layout(location = 3) in int inRepeating;
layout(location = 4) in int inStopOffset;
layout(location = 5) in int inStopCount;
layout(location = 0) out vec2 outPos;
layout(location = 1) out flat Rect outRect;
layout(location = 2) out float outGradientPos;
layout(location = 3) out flat int outRepeating;
layout(location = 4) out flat int outStopOffset;
layout(location = 5) out flat int outStopCount;
float
get_gradient_pos (vec2 pos)
{
pos = pos - inStart * push.scale;
vec2 grad = (inEnd - inStart) * push.scale;
return dot (pos, grad) / dot (grad, grad);
}
void main() {
Rect r = rect_from_gsk (inRect);
vec2 pos = set_position_from_rect (r);
outPos = pos;
outRect = r;
outGradientPos = get_gradient_pos (pos);
outRepeating = inRepeating;
outStopOffset = inStopOffset;
outStopCount = inStopCount;
}

View File

@ -1,42 +0,0 @@
#version 450
#include "common.frag.glsl"
#include "clip.frag.glsl"
#include "rect.frag.glsl"
layout(location = 0) in vec2 in_pos;
layout(location = 1) in flat Rect in_source_rect;
layout(location = 2) in vec2 in_source_coord;
layout(location = 3) in flat uint in_source_id;
layout(location = 4) in flat Rect in_mask_rect;
layout(location = 5) in vec2 in_mask_coord;
layout(location = 6) in flat uint in_mask_id;
layout(location = 7) in flat uint in_mask_mode;
layout(location = 0) out vec4 color;
float
luminance (vec3 color)
{
return dot (vec3 (0.2126, 0.7152, 0.0722), color);
}
void main()
{
vec4 source = texture(get_sampler (in_source_id), in_source_coord);
source *= rect_coverage (in_source_rect, in_pos);
vec4 mask = texture(get_sampler (in_mask_id), in_mask_coord);
mask *= rect_coverage (in_mask_rect, in_pos);
float alpha;
if (in_mask_mode == 0)
alpha = mask.a;
else if (in_mask_mode == 1)
alpha = 1.0 - mask.a;
else if (in_mask_mode == 2)
alpha = luminance (mask.rgb);
else if (in_mask_mode == 3)
alpha = mask.a - luminance (mask.rgb);
color = clip_scaled (in_pos, source * alpha);
}

View File

@ -1,43 +0,0 @@
#version 450
#include "common.vert.glsl"
#include "rect.vert.glsl"
layout(location = 0) in vec4 in_source_rect;
layout(location = 1) in vec4 in_source_tex_rect;
layout(location = 2) in uint in_source_id;
layout(location = 3) in vec4 in_mask_rect;
layout(location = 4) in vec4 in_mask_tex_rect;
layout(location = 5) in uint in_mask_id;
layout(location = 6) in uint in_mask_mode;
layout(location = 0) out vec2 out_pos;
layout(location = 1) out flat Rect out_source_rect;
layout(location = 2) out vec2 out_source_coord;
layout(location = 3) out flat uint out_source_id;
layout(location = 4) out flat Rect out_mask_rect;
layout(location = 5) out vec2 out_mask_coord;
layout(location = 6) out flat uint out_mask_id;
layout(location = 7) out flat uint out_mask_mode;
void main() {
Rect sr = rect_from_gsk (in_source_rect);
Rect mr = rect_from_gsk (in_mask_rect);
Rect r;
if (in_mask_mode == 1)
r = rect_union (sr, mr);
else
r = rect_intersect (sr, mr);
vec2 pos = set_position_from_rect (r);
out_pos = pos;
out_source_rect = sr;
out_source_coord = scale_tex_coord (pos, sr, in_source_tex_rect);
out_source_id = in_source_id;
out_mask_rect = mr;
out_mask_coord = scale_tex_coord (pos, mr, in_mask_tex_rect);
out_mask_id = in_mask_id;
out_mask_mode = in_mask_mode;
}

View File

@ -1,104 +0,0 @@
gsk_private_vulkan_include_shaders = [
'clip.frag.glsl',
'clip.vert.glsl',
'common.frag.glsl',
'common.vert.glsl',
'constants.glsl',
'rect.glsl',
'rect.frag.glsl',
'rect.vert.glsl',
'rounded-rect.glsl',
'rounded-rect.frag.glsl',
]
gsk_private_vulkan_fragment_shaders = [
'blend-mode.frag',
'blur.frag',
'border.frag',
'color.frag',
'color-matrix.frag',
'convert.frag',
'cross-fade.frag',
'glyph.frag',
'inset-shadow.frag',
'linear.frag',
'mask.frag',
'outset-shadow.frag',
'texture.frag',
]
gsk_private_vulkan_vertex_shaders = [
'blend-mode.vert',
'blur.vert',
'border.vert',
'color.vert',
'color-matrix.vert',
'convert.vert',
'cross-fade.vert',
'glyph.vert',
'inset-shadow.vert',
'linear.vert',
'mask.vert',
'outset-shadow.vert',
'texture.vert',
]
gsk_private_vulkan_shaders += gsk_private_vulkan_fragment_shaders
gsk_private_vulkan_shaders += gsk_private_vulkan_vertex_shaders
foreach shader: gsk_private_vulkan_shaders
basefn = shader.split('.').get(0)
suffix = shader.split('.').get(1)
stage_arg = suffix == 'frag' ? '-fshader-stage=fragment' : '-fshader-stage=vertex'
spv_shader = '@0@.@1@.spv'.format(basefn, suffix)
clip_spv_shader = '@0@-clip.@1@.spv'.format(basefn, suffix)
clip_rounded_spv_shader = '@0@-clip-rounded.@1@.spv'.format(basefn, suffix)
compiled_shader = custom_target(spv_shader,
input: shader,
output: spv_shader,
depend_files: gsk_private_vulkan_include_shaders,
command: [
glslc,
stage_arg,
'-DCLIP_NONE',
'@INPUT@',
'-o', '@OUTPUT@'
])
compiled_clip_shader = custom_target(clip_spv_shader,
input: shader,
output: clip_spv_shader,
depend_files: gsk_private_vulkan_include_shaders,
command: [
glslc,
stage_arg,
'-DCLIP_RECT',
'@INPUT@',
'-o', '@OUTPUT@'
])
compiled_clip_rounded_shader = custom_target(clip_rounded_spv_shader,
input: shader,
output: clip_rounded_spv_shader,
depend_files: gsk_private_vulkan_include_shaders,
command: [
glslc,
stage_arg,
'-DCLIP_ROUNDED_RECT',
'@INPUT@',
'-o', '@OUTPUT@'
])
gsk_private_vulkan_compiled_shaders_deps += [compiled_shader, compiled_clip_shader, compiled_clip_rounded_shader]
gsk_private_vulkan_compiled_shaders += [spv_shader, clip_spv_shader, clip_rounded_spv_shader]
endforeach
foreach shader: gsk_private_vulkan_vertex_shaders
shader_header = custom_target(output: '@0@.h'.format(shader),
input: shader,
command: [
find_program('generate-header.py'),
'@INPUT@',
],
capture: true)
gsk_private_vulkan_shader_headers += shader_header
endforeach

View File

@ -1,27 +0,0 @@
#version 450
#include "clip.frag.glsl"
#include "rounded-rect.glsl"
layout(location = 0) in vec2 inPos;
layout(location = 1) in flat vec4 inOutline;
layout(location = 2) in flat vec4 inOutlineCornerWidths;
layout(location = 3) in flat vec4 inOutlineCornerHeights;
layout(location = 4) in flat vec4 inColor;
layout(location = 5) in flat vec2 inOffset;
layout(location = 6) in flat float inSpread;
layout(location = 7) in flat float inBlurRadius;
layout(location = 0) out vec4 color;
void main()
{
RoundedRect outline = RoundedRect (vec4(inOutline.xy, inOutline.xy + inOutline.zw), inOutlineCornerWidths, inOutlineCornerHeights);
RoundedRect outside = rounded_rect_shrink (outline, vec4(-inSpread));
color = vec4(inColor.rgb * inColor.a, inColor.a);
color = color * clamp (rounded_rect_coverage (outside, inPos - inOffset) -
rounded_rect_coverage (outline, inPos),
0.0, 1.0);
color = clip (inPos, color);
}

View File

@ -1,49 +0,0 @@
#version 450
#include "clip.vert.glsl"
layout(location = 0) in mat3x4 inOutline;
layout(location = 3) in vec4 inColor;
layout(location = 4) in vec2 inOffset;
layout(location = 5) in float inSpread;
layout(location = 6) in float inBlurRadius;
layout(location = 0) out vec2 outPos;
layout(location = 1) out flat vec4 outOutline;
layout(location = 2) out flat vec4 outOutlineCornerWidths;
layout(location = 3) out flat vec4 outOutlineCornerHeights;
layout(location = 4) out flat vec4 outColor;
layout(location = 5) out flat vec2 outOffset;
layout(location = 6) out flat float outSpread;
layout(location = 7) out flat float outBlurRadius;
vec2 offsets[6] = { vec2(0.0, 0.0),
vec2(1.0, 0.0),
vec2(0.0, 1.0),
vec2(0.0, 1.0),
vec2(1.0, 0.0),
vec2(1.0, 1.0) };
float radius_pixels(float radius) {
return radius * (3.0 * sqrt(2 * 3.141592653589793) / 4) * 1.5;
}
void main() {
vec4 rect = inOutline[0];
float spread = inSpread + radius_pixels(inBlurRadius);
rect += vec4(inOffset - spread, vec2(2 * spread));
clip (inOutline[0]);
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
outPos = pos;
outOutline = inOutline[0];
outOutlineCornerWidths = inOutline[1];
outOutlineCornerHeights = inOutline[2];
outColor = inColor;
outOffset = inOffset;
outSpread = inSpread;
outBlurRadius = inBlurRadius;
}

View File

@ -1,16 +0,0 @@
#ifndef _RECT_FRAG_
#define _RECT_FRAG_
#include "rect.glsl"
float
rect_coverage (Rect r, vec2 p)
{
vec2 dFdp = abs(fwidth (p));
Rect prect = Rect(vec4(p - 0.5 * dFdp, p + 0.5 * dFdp));
Rect coverect = rect_intersect (r, prect);
vec2 coverage = rect_size(coverect) / dFdp;
return coverage.x * coverage.y;
}
#endif

View File

@ -1,64 +0,0 @@
#ifndef _RECT_
#define _RECT_
struct Rect
{
/* x,y and y,w make up the 2 points of this rect,
note that this is not containing width or height */
vec4 bounds;
};
Rect
rect_from_gsk (vec4 xywh)
{
return Rect((xywh.xyxy + vec4(0,0,xywh.zw)) * push.scale.xyxy);
}
float
rect_distance (Rect r, vec2 p)
{
vec4 distance = (r.bounds - p.xyxy) * vec4(1.0, 1.0, -1.0, -1.0);
vec2 max2 = max (distance.xy, distance.zw);
return length (max (max2, 0)) + min (max(max2.x, max2.y), 0);
}
vec2
rect_size (Rect r)
{
return r.bounds.zw - r.bounds.xy;
}
Rect
rect_round_larger (Rect r)
{
return Rect (vec4 (floor(r.bounds.xy), ceil (r.bounds.zw)));
}
Rect
rect_round_larger_smaller (Rect r)
{
return Rect (mix (floor(r.bounds), ceil (r.bounds), bvec4(0, 1, 1, 0)));
}
Rect
rect_round_smaller_larger (Rect r)
{
return Rect (mix (floor(r.bounds), ceil (r.bounds), bvec4(1, 0, 0, 1)));
}
Rect
rect_intersect (Rect a, Rect b)
{
vec4 result = vec4(max(a.bounds.xy, b.bounds.xy), min(a.bounds.zw, b.bounds.zw));
if (any (greaterThanEqual (result.xy, result.zw)))
return Rect (vec4(0.0));
return Rect(result);
}
Rect
rect_union (Rect a, Rect b)
{
return Rect (vec4 (min (a.bounds.xy, b.bounds.xy), max (a.bounds.zw, b.bounds.zw)));
}
#endif

View File

@ -1,6 +0,0 @@
#ifndef _RECT_VERT_
#define _RECT_VERT_
#include "rect.glsl"
#endif

Some files were not shown because too many files have changed in this diff Show More