mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-11 13:10:07 +00:00
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:
parent
40854f2ae9
commit
1e54e838e0
@ -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 (),
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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',
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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');
|
||||
}
|
@ -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);
|
||||
}
|
@ -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
@ -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);
|
||||
}
|
@ -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 */
|
||||
|
@ -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
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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));
|
||||
}
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
@ -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
|
@ -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));
|
||||
}
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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)]
|
||||
|
@ -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
|
@ -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
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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));
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
@ -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("};")
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
@ -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
|
@ -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
Loading…
Reference in New Issue
Block a user