mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-09 10:20:07 +00:00
Merge branch 'wip/otte/vulkan' into 'main'
Vulkan hacking going overboard See merge request GNOME/gtk!5992
This commit is contained in:
commit
fd5d15004e
@ -1053,26 +1053,30 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
|
||||
device_extensions = g_ptr_array_new ();
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_MAINTENANCE_3_EXTENSION_NAME);
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
if (has_incremental_present)
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
|
||||
|
||||
GDK_DISPLAY_DEBUG (display, VULKAN, "Using Vulkan device %u, queue %u", i, j);
|
||||
if (GDK_VK_CHECK (vkCreateDevice, devices[i],
|
||||
&(VkDeviceCreateInfo) {
|
||||
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
NULL,
|
||||
0,
|
||||
1,
|
||||
&(VkDeviceQueueCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.queueCreateInfoCount = 1,
|
||||
.pQueueCreateInfos = &(VkDeviceQueueCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
||||
.queueFamilyIndex = j,
|
||||
.queueCount = 1,
|
||||
.pQueuePriorities = (float []) { 1.0f },
|
||||
},
|
||||
0,
|
||||
NULL,
|
||||
device_extensions->len,
|
||||
(const char * const *) device_extensions->pdata
|
||||
.enabledExtensionCount = device_extensions->len,
|
||||
.ppEnabledExtensionNames = (const char * const *) device_extensions->pdata,
|
||||
.pNext = &(VkPhysicalDeviceDescriptorIndexingFeatures) {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES,
|
||||
.descriptorBindingPartiallyBound = VK_TRUE,
|
||||
.descriptorBindingVariableDescriptorCount = VK_TRUE,
|
||||
.descriptorBindingSampledImageUpdateAfterBind = VK_TRUE,
|
||||
}
|
||||
},
|
||||
NULL,
|
||||
&display->vk_device) != VK_SUCCESS)
|
||||
@ -1144,6 +1148,7 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
|
||||
|
||||
used_extensions = g_ptr_array_new ();
|
||||
g_ptr_array_add (used_extensions, (gpointer) VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
g_ptr_array_add (used_extensions, (gpointer) VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
g_ptr_array_add (used_extensions, (gpointer) GDK_DISPLAY_GET_CLASS (display)->vk_extension_name);
|
||||
|
||||
for (i = 0; i < n_extensions; i++)
|
||||
@ -1215,7 +1220,7 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
|
||||
.enabledLayerCount = used_layers->len,
|
||||
.ppEnabledLayerNames = (const char * const *) used_layers->pdata,
|
||||
.enabledExtensionCount = used_extensions->len,
|
||||
.ppEnabledExtensionNames = (const char * const *) used_extensions->pdata
|
||||
.ppEnabledExtensionNames = (const char * const *) used_extensions->pdata,
|
||||
},
|
||||
NULL,
|
||||
&display->vk_instance);
|
||||
|
@ -372,6 +372,8 @@ gsk_renderer_render_texture (GskRenderer *renderer,
|
||||
gsk_render_node_get_bounds (root, &real_viewport);
|
||||
viewport = &real_viewport;
|
||||
}
|
||||
g_return_val_if_fail (viewport->size.width > 0, NULL);
|
||||
g_return_val_if_fail (viewport->size.height > 0, NULL);
|
||||
|
||||
texture = GSK_RENDERER_GET_CLASS (renderer)->render_texture (renderer, root, viewport);
|
||||
|
||||
|
@ -689,6 +689,134 @@ gsk_rounded_rect_intersect_with_rect (const GskRoundedRect *self,
|
||||
return GSK_INTERSECTION_NONEMPTY;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_nonintersecting_corner (const GskRoundedRect *out,
|
||||
const GskRoundedRect *in,
|
||||
GskCorner corner,
|
||||
float diff_x,
|
||||
float diff_y,
|
||||
GskRoundedRect *result)
|
||||
{
|
||||
g_assert (diff_x >= 0);
|
||||
g_assert (diff_y >= 0);
|
||||
|
||||
if (out->corner[corner].width < diff_x ||
|
||||
out->corner[corner].height < diff_y ||
|
||||
(out->corner[corner].width <= in->corner[corner].width + diff_x &&
|
||||
out->corner[corner].height <= in->corner[corner].height + diff_y))
|
||||
{
|
||||
result->corner[corner] = in->corner[corner];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (diff_x > 0 || diff_y > 0)
|
||||
return FALSE;
|
||||
|
||||
if (out->corner[corner].width > in->corner[corner].width &&
|
||||
out->corner[corner].height > in->corner[corner].height)
|
||||
{
|
||||
result->corner[corner] = out->corner[corner];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* a is outside in x direction, b is outside in y direction */
|
||||
static gboolean
|
||||
check_intersecting_corner (const GskRoundedRect *a,
|
||||
const GskRoundedRect *b,
|
||||
GskCorner corner,
|
||||
float diff_x,
|
||||
float diff_y,
|
||||
GskRoundedRect *result)
|
||||
{
|
||||
g_assert (diff_x > 0);
|
||||
g_assert (diff_y > 0);
|
||||
|
||||
if (diff_x < a->corner[corner].width ||
|
||||
diff_x > a->bounds.size.width - a->corner[corner].width - a->corner[OPPOSITE_CORNER_X (corner)].width ||
|
||||
diff_y < b->corner[corner].height ||
|
||||
diff_y > b->bounds.size.height - b->corner[corner].height - b->corner[OPPOSITE_CORNER_Y (corner)].height)
|
||||
return FALSE;
|
||||
|
||||
result->corner[corner] = GRAPHENE_SIZE_INIT (0, 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_corner (const GskRoundedRect *a,
|
||||
const GskRoundedRect *b,
|
||||
GskCorner corner,
|
||||
float diff_x,
|
||||
float diff_y,
|
||||
GskRoundedRect *result)
|
||||
{
|
||||
if (diff_x >= 0)
|
||||
{
|
||||
if (diff_y >= 0)
|
||||
{
|
||||
return check_nonintersecting_corner (a, b, corner, diff_x, diff_y, result);
|
||||
}
|
||||
else if (diff_x == 0)
|
||||
{
|
||||
return check_nonintersecting_corner (b, a, corner, 0, - diff_y, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
return check_intersecting_corner (a, b, corner, diff_x, - diff_y, result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (diff_y <= 0)
|
||||
{
|
||||
return check_nonintersecting_corner (b, a, corner, - diff_x, - diff_y, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
return check_intersecting_corner (b, a, corner, - diff_x, diff_y, result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GskRoundedRectIntersection
|
||||
gsk_rounded_rect_intersection (const GskRoundedRect *a,
|
||||
const GskRoundedRect *b,
|
||||
GskRoundedRect *result)
|
||||
{
|
||||
float top, left, bottom, right;
|
||||
|
||||
if (!graphene_rect_intersection (&a->bounds, &b->bounds, &result->bounds))
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
|
||||
left = b->bounds.origin.x - a->bounds.origin.x;
|
||||
top = b->bounds.origin.y - a->bounds.origin.y;
|
||||
right = a->bounds.origin.x + a->bounds.size.width - b->bounds.origin.x - b->bounds.size.width;
|
||||
bottom = a->bounds.origin.y + a->bounds.size.height - b->bounds.origin.y - b->bounds.size.height;
|
||||
|
||||
if (check_corner (a, b,
|
||||
GSK_CORNER_TOP_LEFT,
|
||||
left, top,
|
||||
result) &&
|
||||
check_corner (a, b,
|
||||
GSK_CORNER_TOP_RIGHT,
|
||||
right, top,
|
||||
result) &&
|
||||
check_corner (a, b,
|
||||
GSK_CORNER_BOTTOM_LEFT,
|
||||
left, bottom,
|
||||
result) &&
|
||||
check_corner (a, b,
|
||||
GSK_CORNER_BOTTOM_RIGHT,
|
||||
right, bottom,
|
||||
result))
|
||||
return GSK_INTERSECTION_NONEMPTY;
|
||||
|
||||
return GSK_INTERSECTION_NOT_REPRESENTABLE;
|
||||
}
|
||||
|
||||
static void
|
||||
append_arc (cairo_t *cr, double angle1, double angle2, gboolean negative)
|
||||
{
|
||||
@ -766,13 +894,14 @@ gsk_rounded_rect_path (const GskRoundedRect *self,
|
||||
* only look at the last vec4 if they have to.
|
||||
*/
|
||||
void
|
||||
gsk_rounded_rect_to_float (const GskRoundedRect *self,
|
||||
float rect[12])
|
||||
gsk_rounded_rect_to_float (const GskRoundedRect *self,
|
||||
const graphene_point_t *offset,
|
||||
float rect[12])
|
||||
{
|
||||
guint i;
|
||||
|
||||
rect[0] = self->bounds.origin.x;
|
||||
rect[1] = self->bounds.origin.y;
|
||||
rect[0] = self->bounds.origin.x + offset->x;
|
||||
rect[1] = self->bounds.origin.y + offset->y;
|
||||
rect[2] = self->bounds.size.width;
|
||||
rect[3] = self->bounds.size.height;
|
||||
|
||||
|
@ -6,6 +6,24 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OPPOSITE_CORNER(corner) ((corner) ^ 2)
|
||||
G_STATIC_ASSERT (OPPOSITE_CORNER (GSK_CORNER_TOP_LEFT) == GSK_CORNER_BOTTOM_RIGHT);
|
||||
G_STATIC_ASSERT (OPPOSITE_CORNER (GSK_CORNER_TOP_RIGHT) == GSK_CORNER_BOTTOM_LEFT);
|
||||
G_STATIC_ASSERT (OPPOSITE_CORNER (GSK_CORNER_BOTTOM_LEFT) == GSK_CORNER_TOP_RIGHT);
|
||||
G_STATIC_ASSERT (OPPOSITE_CORNER (GSK_CORNER_BOTTOM_RIGHT) == GSK_CORNER_TOP_LEFT);
|
||||
|
||||
#define OPPOSITE_CORNER_X(corner) ((corner) ^ 1)
|
||||
G_STATIC_ASSERT (OPPOSITE_CORNER_X (GSK_CORNER_TOP_LEFT) == GSK_CORNER_TOP_RIGHT);
|
||||
G_STATIC_ASSERT (OPPOSITE_CORNER_X (GSK_CORNER_TOP_RIGHT) == GSK_CORNER_TOP_LEFT);
|
||||
G_STATIC_ASSERT (OPPOSITE_CORNER_X (GSK_CORNER_BOTTOM_LEFT) == GSK_CORNER_BOTTOM_RIGHT);
|
||||
G_STATIC_ASSERT (OPPOSITE_CORNER_X (GSK_CORNER_BOTTOM_RIGHT) == GSK_CORNER_BOTTOM_LEFT);
|
||||
|
||||
#define OPPOSITE_CORNER_Y(corner) ((corner) ^ 3)
|
||||
G_STATIC_ASSERT (OPPOSITE_CORNER_Y (GSK_CORNER_TOP_LEFT) == GSK_CORNER_BOTTOM_LEFT);
|
||||
G_STATIC_ASSERT (OPPOSITE_CORNER_Y (GSK_CORNER_TOP_RIGHT) == GSK_CORNER_BOTTOM_RIGHT);
|
||||
G_STATIC_ASSERT (OPPOSITE_CORNER_Y (GSK_CORNER_BOTTOM_LEFT) == GSK_CORNER_TOP_LEFT);
|
||||
G_STATIC_ASSERT (OPPOSITE_CORNER_Y (GSK_CORNER_BOTTOM_RIGHT) == GSK_CORNER_TOP_RIGHT);
|
||||
|
||||
#define GSK_ROUNDED_RECT_INIT_FROM_RECT(_r) \
|
||||
(GskRoundedRect) { .bounds = _r, \
|
||||
.corner = { \
|
||||
@ -28,6 +46,7 @@ gboolean gsk_rounded_rect_is_circular (const GskRounde
|
||||
void gsk_rounded_rect_path (const GskRoundedRect *self,
|
||||
cairo_t *cr);
|
||||
void gsk_rounded_rect_to_float (const GskRoundedRect *self,
|
||||
const graphene_point_t *offset,
|
||||
float rect[12]);
|
||||
|
||||
gboolean gsk_rounded_rect_equal (gconstpointer rect1,
|
||||
@ -43,6 +62,9 @@ typedef enum {
|
||||
GskRoundedRectIntersection gsk_rounded_rect_intersect_with_rect (const GskRoundedRect *self,
|
||||
const graphene_rect_t *rect,
|
||||
GskRoundedRect *result) G_GNUC_PURE;
|
||||
GskRoundedRectIntersection gsk_rounded_rect_intersection (const GskRoundedRect *a,
|
||||
const GskRoundedRect *b,
|
||||
GskRoundedRect *result);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -12,8 +12,12 @@ typedef struct _GskVulkanBlendModeInstance GskVulkanBlendModeInstance;
|
||||
struct _GskVulkanBlendModeInstance
|
||||
{
|
||||
float rect[4];
|
||||
float start_tex_rect[4];
|
||||
float end_tex_rect[4];
|
||||
float top_rect[4];
|
||||
float bottom_rect[4];
|
||||
float top_tex_rect[4];
|
||||
float bottom_tex_rect[4];
|
||||
guint32 top_tex_id[2];
|
||||
guint32 bottom_tex_id[2];
|
||||
guint32 blend_mode;
|
||||
};
|
||||
|
||||
@ -40,18 +44,42 @@ gsk_vulkan_blend_mode_pipeline_get_input_state_create_info (GskVulkanPipeline *s
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanBlendModeInstance, start_tex_rect),
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanBlendModeInstance, top_rect),
|
||||
},
|
||||
{
|
||||
.location = 2,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanBlendModeInstance, end_tex_rect),
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanBlendModeInstance, bottom_rect),
|
||||
},
|
||||
{
|
||||
.location = 3,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanBlendModeInstance, top_tex_rect),
|
||||
},
|
||||
{
|
||||
.location = 4,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanBlendModeInstance, bottom_tex_rect),
|
||||
},
|
||||
{
|
||||
.location = 5,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32_UINT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanBlendModeInstance, top_tex_id),
|
||||
},
|
||||
{
|
||||
.location = 6,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_UINT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanBlendModeInstance, bottom_tex_id),
|
||||
},
|
||||
{
|
||||
.location = 7,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_UINT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanBlendModeInstance, blend_mode),
|
||||
}
|
||||
};
|
||||
@ -98,37 +126,50 @@ gsk_vulkan_blend_mode_pipeline_new (GdkVulkanContext *context,
|
||||
return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_BLEND_MODE_PIPELINE, context, layout, shader_name, render_pass);
|
||||
}
|
||||
|
||||
gsize
|
||||
gsk_vulkan_blend_mode_pipeline_count_vertex_data (GskVulkanBlendModePipeline *pipeline)
|
||||
{
|
||||
return sizeof (GskVulkanBlendModeInstance);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_blend_mode_pipeline_collect_vertex_data (GskVulkanBlendModePipeline *pipeline,
|
||||
guchar *data,
|
||||
const graphene_rect_t *bounds,
|
||||
const graphene_rect_t *start_tex_rect,
|
||||
const graphene_rect_t *end_tex_rect,
|
||||
GskBlendMode blend_mode)
|
||||
guchar *data,
|
||||
guint32 top_tex_id[2],
|
||||
guint32 bottom_tex_id[2],
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *bounds,
|
||||
const graphene_rect_t *top_bounds,
|
||||
const graphene_rect_t *bottom_bounds,
|
||||
const graphene_rect_t *top_tex_rect,
|
||||
const graphene_rect_t *bottom_tex_rect,
|
||||
GskBlendMode blend_mode)
|
||||
{
|
||||
GskVulkanBlendModeInstance *instance = (GskVulkanBlendModeInstance *) data;
|
||||
|
||||
instance->rect[0] = bounds->origin.x;
|
||||
instance->rect[1] = bounds->origin.y;
|
||||
instance->rect[0] = bounds->origin.x + offset->x;
|
||||
instance->rect[1] = bounds->origin.y + offset->y;
|
||||
instance->rect[2] = bounds->size.width;
|
||||
instance->rect[3] = bounds->size.height;
|
||||
|
||||
instance->start_tex_rect[0] = start_tex_rect->origin.x;
|
||||
instance->start_tex_rect[1] = start_tex_rect->origin.y;
|
||||
instance->start_tex_rect[2] = start_tex_rect->size.width;
|
||||
instance->start_tex_rect[3] = start_tex_rect->size.height;
|
||||
instance->top_rect[0] = top_bounds->origin.x + offset->x;
|
||||
instance->top_rect[1] = top_bounds->origin.y + offset->y;
|
||||
instance->top_rect[2] = top_bounds->size.width;
|
||||
instance->top_rect[3] = top_bounds->size.height;
|
||||
|
||||
instance->end_tex_rect[0] = end_tex_rect->origin.x;
|
||||
instance->end_tex_rect[1] = end_tex_rect->origin.y;
|
||||
instance->end_tex_rect[2] = end_tex_rect->size.width;
|
||||
instance->end_tex_rect[3] = end_tex_rect->size.height;
|
||||
instance->bottom_rect[0] = bottom_bounds->origin.x + offset->x;
|
||||
instance->bottom_rect[1] = bottom_bounds->origin.y + offset->y;
|
||||
instance->bottom_rect[2] = bottom_bounds->size.width;
|
||||
instance->bottom_rect[3] = bottom_bounds->size.height;
|
||||
|
||||
instance->top_tex_rect[0] = top_tex_rect->origin.x;
|
||||
instance->top_tex_rect[1] = top_tex_rect->origin.y;
|
||||
instance->top_tex_rect[2] = top_tex_rect->size.width;
|
||||
instance->top_tex_rect[3] = top_tex_rect->size.height;
|
||||
|
||||
instance->bottom_tex_rect[0] = bottom_tex_rect->origin.x;
|
||||
instance->bottom_tex_rect[1] = bottom_tex_rect->origin.y;
|
||||
instance->bottom_tex_rect[2] = bottom_tex_rect->size.width;
|
||||
instance->bottom_tex_rect[3] = bottom_tex_rect->size.height;
|
||||
|
||||
instance->top_tex_id[0] = top_tex_id[0];
|
||||
instance->top_tex_id[1] = top_tex_id[1];
|
||||
instance->bottom_tex_id[0] = bottom_tex_id[0];
|
||||
instance->bottom_tex_id[1] = bottom_tex_id[1];
|
||||
instance->blend_mode = blend_mode;
|
||||
}
|
||||
|
||||
|
@ -18,12 +18,16 @@ GskVulkanPipeline * gsk_vulkan_blend_mode_pipeline_new (GdkVulka
|
||||
const char *shader_name,
|
||||
VkRenderPass render_pass);
|
||||
|
||||
gsize gsk_vulkan_blend_mode_pipeline_count_vertex_data (GskVulkanBlendModePipeline *pipeline);
|
||||
void gsk_vulkan_blend_mode_pipeline_collect_vertex_data (GskVulkanBlendModePipeline *pipeline,
|
||||
guchar *data,
|
||||
guint32 top_tex_id[2],
|
||||
guint32 bottom_tex_id[2],
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *bounds,
|
||||
const graphene_rect_t *start_bounds,
|
||||
const graphene_rect_t *end_bounds,
|
||||
const graphene_rect_t *top_bounds,
|
||||
const graphene_rect_t *bottom_bounds,
|
||||
const graphene_rect_t *top_tex_rect,
|
||||
const graphene_rect_t *bottom_tex_rect,
|
||||
GskBlendMode blend_mode);
|
||||
gsize gsk_vulkan_blend_mode_pipeline_draw (GskVulkanBlendModePipeline *pipeline,
|
||||
VkCommandBuffer command_buffer,
|
||||
|
@ -14,6 +14,7 @@ struct _GskVulkanBlurInstance
|
||||
float rect[4];
|
||||
float tex_rect[4];
|
||||
float blur_radius;
|
||||
guint32 tex_id[2];
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskVulkanBlurPipeline, gsk_vulkan_blur_pipeline, GSK_TYPE_VULKAN_PIPELINE)
|
||||
@ -46,6 +47,12 @@ gsk_vulkan_blur_pipeline_get_input_state_create_info (GskVulkanPipeline *self)
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32_SFLOAT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanBlurInstance, blur_radius),
|
||||
},
|
||||
{
|
||||
.location = 3,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_UINT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanBlurInstance, tex_id),
|
||||
}
|
||||
};
|
||||
static const VkPipelineVertexInputStateCreateInfo info = {
|
||||
@ -91,23 +98,19 @@ gsk_vulkan_blur_pipeline_new (GdkVulkanContext *context,
|
||||
return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_BLUR_PIPELINE, context, layout, shader_name, render_pass);
|
||||
}
|
||||
|
||||
gsize
|
||||
gsk_vulkan_blur_pipeline_count_vertex_data (GskVulkanBlurPipeline *pipeline)
|
||||
{
|
||||
return sizeof (GskVulkanBlurInstance);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_blur_pipeline_collect_vertex_data (GskVulkanBlurPipeline *pipeline,
|
||||
guchar *data,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_rect_t *tex_rect,
|
||||
double blur_radius)
|
||||
gsk_vulkan_blur_pipeline_collect_vertex_data (GskVulkanBlurPipeline *pipeline,
|
||||
guchar *data,
|
||||
guint32 tex_id[2],
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_rect_t *tex_rect,
|
||||
double blur_radius)
|
||||
{
|
||||
GskVulkanBlurInstance *instance = (GskVulkanBlurInstance *) data;
|
||||
|
||||
instance->rect[0] = rect->origin.x;
|
||||
instance->rect[1] = rect->origin.y;
|
||||
instance->rect[0] = rect->origin.x + offset->x;
|
||||
instance->rect[1] = rect->origin.y + offset->y;
|
||||
instance->rect[2] = rect->size.width;
|
||||
instance->rect[3] = rect->size.height;
|
||||
instance->tex_rect[0] = tex_rect->origin.x;
|
||||
@ -115,6 +118,8 @@ gsk_vulkan_blur_pipeline_collect_vertex_data (GskVulkanBlurPipeline *pipeline,
|
||||
instance->tex_rect[2] = tex_rect->size.width;
|
||||
instance->tex_rect[3] = tex_rect->size.height;
|
||||
instance->blur_radius = blur_radius;
|
||||
instance->tex_id[0] = tex_id[0];
|
||||
instance->tex_id[1] = tex_id[1];
|
||||
}
|
||||
|
||||
gsize
|
||||
|
@ -17,9 +17,10 @@ GskVulkanPipeline * gsk_vulkan_blur_pipeline_new (GdkVulka
|
||||
const char *shader_name,
|
||||
VkRenderPass render_pass);
|
||||
|
||||
gsize gsk_vulkan_blur_pipeline_count_vertex_data (GskVulkanBlurPipeline *pipeline);
|
||||
void gsk_vulkan_blur_pipeline_collect_vertex_data (GskVulkanBlurPipeline *pipeline,
|
||||
guchar *data,
|
||||
guint32 tex_id[2],
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_rect_t *tex_rect,
|
||||
double radius);
|
||||
|
@ -123,15 +123,10 @@ gsk_vulkan_border_pipeline_new (GdkVulkanContext *context,
|
||||
return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_BORDER_PIPELINE, context, layout, shader_name, render_pass);
|
||||
}
|
||||
|
||||
gsize
|
||||
gsk_vulkan_border_pipeline_count_vertex_data (GskVulkanBorderPipeline *pipeline)
|
||||
{
|
||||
return sizeof (GskVulkanBorderInstance);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_border_pipeline_collect_vertex_data (GskVulkanBorderPipeline *pipeline,
|
||||
guchar *data,
|
||||
const graphene_point_t *offset,
|
||||
const GskRoundedRect *rect,
|
||||
const float widths[4],
|
||||
const GdkRGBA colors[4])
|
||||
@ -139,7 +134,7 @@ gsk_vulkan_border_pipeline_collect_vertex_data (GskVulkanBorderPipeline *pipelin
|
||||
GskVulkanBorderInstance *instance = (GskVulkanBorderInstance *) data;
|
||||
guint i;
|
||||
|
||||
gsk_rounded_rect_to_float (rect, instance->rect);
|
||||
gsk_rounded_rect_to_float (rect, offset, instance->rect);
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
instance->widths[i] = widths[i];
|
||||
|
@ -18,9 +18,9 @@ GskVulkanPipeline * gsk_vulkan_border_pipeline_new (GdkVulk
|
||||
const char *shader_name,
|
||||
VkRenderPass render_pass);
|
||||
|
||||
gsize gsk_vulkan_border_pipeline_count_vertex_data (GskVulkanBorderPipeline *pipeline);
|
||||
void gsk_vulkan_border_pipeline_collect_vertex_data (GskVulkanBorderPipeline *pipeline,
|
||||
guchar *data,
|
||||
const graphene_point_t *offset,
|
||||
const GskRoundedRect *rect,
|
||||
const float widths[4],
|
||||
const GdkRGBA colors[4]);
|
||||
|
@ -119,15 +119,10 @@ gsk_vulkan_box_shadow_pipeline_new (GdkVulkanContext *context,
|
||||
return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_BOX_SHADOW_PIPELINE, context, layout, shader_name, render_pass);
|
||||
}
|
||||
|
||||
gsize
|
||||
gsk_vulkan_box_shadow_pipeline_count_vertex_data (GskVulkanBoxShadowPipeline *pipeline)
|
||||
{
|
||||
return sizeof (GskVulkanBoxShadowInstance);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_box_shadow_pipeline_collect_vertex_data (GskVulkanBoxShadowPipeline *pipeline,
|
||||
guchar *data,
|
||||
const graphene_point_t *offset,
|
||||
const GskRoundedRect *outline,
|
||||
const GdkRGBA *color,
|
||||
float dx,
|
||||
@ -137,7 +132,7 @@ gsk_vulkan_box_shadow_pipeline_collect_vertex_data (GskVulkanBoxShadowPipeline *
|
||||
{
|
||||
GskVulkanBoxShadowInstance *instance = (GskVulkanBoxShadowInstance *) data;
|
||||
|
||||
gsk_rounded_rect_to_float (outline, instance->outline);
|
||||
gsk_rounded_rect_to_float (outline, offset, instance->outline);
|
||||
instance->color[0] = color->red;
|
||||
instance->color[1] = color->green;
|
||||
instance->color[2] = color->blue;
|
||||
|
@ -18,9 +18,9 @@ GskVulkanPipeline * gsk_vulkan_box_shadow_pipeline_new (GdkVulk
|
||||
const char *shader_name,
|
||||
VkRenderPass render_pass);
|
||||
|
||||
gsize gsk_vulkan_box_shadow_pipeline_count_vertex_data (GskVulkanBoxShadowPipeline *pipeline);
|
||||
void gsk_vulkan_box_shadow_pipeline_collect_vertex_data (GskVulkanBoxShadowPipeline *pipeline,
|
||||
guchar *data,
|
||||
const graphene_point_t *offset,
|
||||
const GskRoundedRect *outline,
|
||||
const GdkRGBA *color,
|
||||
float dx,
|
||||
|
@ -13,7 +13,15 @@ gsk_vulkan_clip_init_empty (GskVulkanClip *clip,
|
||||
gsk_rounded_rect_init_from_rect (&clip->rect, rect, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
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)
|
||||
{
|
||||
@ -21,11 +29,30 @@ gsk_vulkan_clip_init_copy (GskVulkanClip *self,
|
||||
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);
|
||||
@ -57,22 +84,10 @@ gsk_vulkan_clip_intersect_rect (GskVulkanClip *dest,
|
||||
dest->type = GSK_VULKAN_CLIP_ALL_CLIPPED;
|
||||
break;
|
||||
|
||||
case GSK_VULKAN_CLIP_ROUNDED_CIRCULAR:
|
||||
case GSK_VULKAN_CLIP_ROUNDED:
|
||||
if (gsk_rounded_rect_contains_rect (&src->rect, rect))
|
||||
{
|
||||
dest->type = GSK_VULKAN_CLIP_RECT;
|
||||
gsk_rounded_rect_init_from_rect (&dest->rect, rect, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* some points of rect are inside src's rounded rect,
|
||||
* some are outside. */
|
||||
/* XXX: If the 2 rects don't intersect on rounded corners,
|
||||
* we could actually compute a new clip here.
|
||||
*/
|
||||
return FALSE;
|
||||
}
|
||||
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:
|
||||
@ -88,6 +103,8 @@ 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);
|
||||
@ -106,34 +123,21 @@ gsk_vulkan_clip_intersect_rounded_rect (GskVulkanClip *dest,
|
||||
break;
|
||||
|
||||
case GSK_VULKAN_CLIP_NONE:
|
||||
dest->type = gsk_rounded_rect_is_circular (rounded) ? GSK_VULKAN_CLIP_ROUNDED_CIRCULAR : GSK_VULKAN_CLIP_ROUNDED;
|
||||
dest->type = GSK_VULKAN_CLIP_ROUNDED;
|
||||
gsk_rounded_rect_init_copy (&dest->rect, rounded);
|
||||
break;
|
||||
|
||||
case GSK_VULKAN_CLIP_RECT:
|
||||
if (graphene_rect_contains_rect (&src->rect.bounds, &rounded->bounds))
|
||||
{
|
||||
dest->type = gsk_rounded_rect_is_circular (rounded) ? GSK_VULKAN_CLIP_ROUNDED_CIRCULAR : GSK_VULKAN_CLIP_ROUNDED;
|
||||
gsk_rounded_rect_init_copy (&dest->rect, rounded);
|
||||
return TRUE;
|
||||
}
|
||||
/* some points of rect are inside src's rounded rect,
|
||||
* some are outside. */
|
||||
/* XXX: If the 2 rects don't intersect on rounded corners,
|
||||
* we could actually compute a new clip here.
|
||||
*/
|
||||
return FALSE;
|
||||
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_CIRCULAR:
|
||||
case GSK_VULKAN_CLIP_ROUNDED:
|
||||
if (gsk_rounded_rect_contains_rect (&src->rect, &rounded->bounds))
|
||||
{
|
||||
dest->type = gsk_rounded_rect_is_circular (rounded) ? GSK_VULKAN_CLIP_ROUNDED_CIRCULAR : GSK_VULKAN_CLIP_ROUNDED;
|
||||
gsk_rounded_rect_init_copy (&dest->rect, rounded);
|
||||
return TRUE;
|
||||
}
|
||||
/* XXX: Can be improved for the case where one of the rects is a slightly shrunk version of the other */
|
||||
return FALSE;
|
||||
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 ();
|
||||
@ -143,6 +147,19 @@ gsk_vulkan_clip_intersect_rounded_rect (GskVulkanClip *dest,
|
||||
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,
|
||||
@ -164,7 +181,6 @@ gsk_vulkan_clip_transform (GskVulkanClip *dest,
|
||||
return TRUE;
|
||||
|
||||
case GSK_VULKAN_CLIP_RECT:
|
||||
case GSK_VULKAN_CLIP_ROUNDED_CIRCULAR:
|
||||
case GSK_VULKAN_CLIP_ROUNDED:
|
||||
switch (gsk_transform_get_category (transform))
|
||||
{
|
||||
@ -220,9 +236,14 @@ gsk_vulkan_clip_transform (GskVulkanClip *dest,
|
||||
}
|
||||
|
||||
gboolean
|
||||
gsk_vulkan_clip_contains_rect (const GskVulkanClip *self,
|
||||
const graphene_rect_t *rect)
|
||||
gsk_vulkan_clip_intersects_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:
|
||||
@ -234,10 +255,36 @@ gsk_vulkan_clip_contains_rect (const GskVulkanClip *self,
|
||||
return TRUE;
|
||||
|
||||
case GSK_VULKAN_CLIP_RECT:
|
||||
return graphene_rect_contains_rect (&self->rect.bounds, rect);
|
||||
return graphene_rect_intersection (&self->rect.bounds, &r, NULL);
|
||||
|
||||
case GSK_VULKAN_CLIP_ROUNDED_CIRCULAR:
|
||||
case GSK_VULKAN_CLIP_ROUNDED:
|
||||
return gsk_rounded_rect_contains_rect (&self->rect, rect);
|
||||
return gsk_rounded_rect_intersects_rect (&self->rect, &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);
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,6 @@ typedef enum {
|
||||
GSK_VULKAN_CLIP_NONE,
|
||||
/* The clip is a rectangular area */
|
||||
GSK_VULKAN_CLIP_RECT,
|
||||
/* The clip is a rounded rectangle, and for every corner
|
||||
* corner.width == corner.height is true
|
||||
*/
|
||||
GSK_VULKAN_CLIP_ROUNDED_CIRCULAR,
|
||||
/* The clip is a rounded rectangle */
|
||||
GSK_VULKAN_CLIP_ROUNDED
|
||||
} GskVulkanClipComplexity;
|
||||
@ -36,6 +32,10 @@ struct _GskVulkanClip
|
||||
|
||||
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,
|
||||
@ -43,12 +43,20 @@ gboolean gsk_vulkan_clip_intersect_rect (GskVulk
|
||||
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_intersects_rect (const GskVulkanClip *self,
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *rect) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -84,22 +84,17 @@ gsk_vulkan_color_pipeline_new (GdkVulkanContext *context,
|
||||
return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_COLOR_PIPELINE, context, layout, shader_name, render_pass);
|
||||
}
|
||||
|
||||
gsize
|
||||
gsk_vulkan_color_pipeline_count_vertex_data (GskVulkanColorPipeline *pipeline)
|
||||
{
|
||||
return sizeof (GskVulkanColorInstance);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_color_pipeline_collect_vertex_data (GskVulkanColorPipeline *pipeline,
|
||||
guchar *data,
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *rect,
|
||||
const GdkRGBA *color)
|
||||
{
|
||||
GskVulkanColorInstance *instance = (GskVulkanColorInstance *) data;
|
||||
|
||||
instance->rect[0] = rect->origin.x;
|
||||
instance->rect[1] = rect->origin.y;
|
||||
instance->rect[0] = rect->origin.x + offset->x;
|
||||
instance->rect[1] = rect->origin.y + offset->y;
|
||||
instance->rect[2] = rect->size.width;
|
||||
instance->rect[3] = rect->size.height;
|
||||
instance->color[0] = color->red;
|
||||
|
@ -17,9 +17,9 @@ GskVulkanPipeline * gsk_vulkan_color_pipeline_new (GdkVulk
|
||||
const char *shader_name,
|
||||
VkRenderPass render_pass);
|
||||
|
||||
gsize gsk_vulkan_color_pipeline_count_vertex_data (GskVulkanColorPipeline *pipeline);
|
||||
void gsk_vulkan_color_pipeline_collect_vertex_data (GskVulkanColorPipeline *pipeline,
|
||||
guchar *data,
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *rect,
|
||||
const GdkRGBA *color);
|
||||
gsize gsk_vulkan_color_pipeline_draw (GskVulkanColorPipeline *pipeline,
|
||||
|
@ -13,6 +13,7 @@ struct _GskVulkanColorTextInstance
|
||||
{
|
||||
float rect[4];
|
||||
float tex_rect[4];
|
||||
guint32 tex_id[2];
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskVulkanColorTextPipeline, gsk_vulkan_color_text_pipeline, GSK_TYPE_VULKAN_PIPELINE)
|
||||
@ -40,6 +41,12 @@ gsk_vulkan_color_text_pipeline_get_input_state_create_info (GskVulkanPipeline *s
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanColorTextInstance, tex_rect),
|
||||
},
|
||||
{
|
||||
.location = 2,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_UINT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanColorTextInstance, tex_id),
|
||||
}
|
||||
};
|
||||
static const VkPipelineVertexInputStateCreateInfo info = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||
@ -84,18 +91,12 @@ gsk_vulkan_color_text_pipeline_new (GdkVulkanContext *context,
|
||||
return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_COLOR_TEXT_PIPELINE, context, layout, shader_name, render_pass);
|
||||
}
|
||||
|
||||
gsize
|
||||
gsk_vulkan_color_text_pipeline_count_vertex_data (GskVulkanColorTextPipeline *pipeline,
|
||||
int num_instances)
|
||||
{
|
||||
return sizeof (GskVulkanColorTextInstance) * num_instances;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline *pipeline,
|
||||
guchar *data,
|
||||
GskVulkanRenderer *renderer,
|
||||
const graphene_rect_t *rect,
|
||||
guint tex_id[2],
|
||||
PangoFont *font,
|
||||
guint total_glyphs,
|
||||
const PangoGlyphInfo *glyphs,
|
||||
@ -140,6 +141,9 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline *
|
||||
instance->tex_rect[2] = glyph->tw;
|
||||
instance->tex_rect[3] = glyph->th;
|
||||
|
||||
instance->tex_id[0] = tex_id[0];
|
||||
instance->tex_id[1] = tex_id[1];
|
||||
|
||||
count++;
|
||||
}
|
||||
x_position += gi->geometry.width;
|
||||
|
@ -18,12 +18,11 @@ GskVulkanPipeline * gsk_vulkan_color_text_pipeline_new (Gd
|
||||
const char *shader_name,
|
||||
VkRenderPass render_pass);
|
||||
|
||||
gsize gsk_vulkan_color_text_pipeline_count_vertex_data (GskVulkanColorTextPipeline *pipeline,
|
||||
int num_instances);
|
||||
void gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline *pipeline,
|
||||
guchar *data,
|
||||
GskVulkanRenderer *renderer,
|
||||
const graphene_rect_t *rect,
|
||||
guint tex_id[2],
|
||||
PangoFont *font,
|
||||
guint total_glyphs,
|
||||
const PangoGlyphInfo *glyphs,
|
||||
|
@ -12,8 +12,12 @@ typedef struct _GskVulkanCrossFadeInstance GskVulkanCrossFadeInstance;
|
||||
struct _GskVulkanCrossFadeInstance
|
||||
{
|
||||
float rect[4];
|
||||
float start_rect[4];
|
||||
float end_rect[4];
|
||||
float start_tex_rect[4];
|
||||
float end_tex_rect[4];
|
||||
guint32 start_tex_id[2];
|
||||
guint32 end_tex_id[2];
|
||||
float progress;
|
||||
};
|
||||
|
||||
@ -40,17 +44,41 @@ gsk_vulkan_cross_fade_pipeline_get_input_state_create_info (GskVulkanPipeline *s
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanCrossFadeInstance, start_tex_rect),
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanCrossFadeInstance, start_rect),
|
||||
},
|
||||
{
|
||||
.location = 2,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanCrossFadeInstance, end_tex_rect),
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanCrossFadeInstance, end_rect),
|
||||
},
|
||||
{
|
||||
.location = 3,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanCrossFadeInstance, start_tex_rect),
|
||||
},
|
||||
{
|
||||
.location = 4,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanCrossFadeInstance, end_tex_rect),
|
||||
},
|
||||
{
|
||||
.location = 5,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_UINT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanCrossFadeInstance, start_tex_id),
|
||||
},
|
||||
{
|
||||
.location = 6,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_UINT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanCrossFadeInstance, end_tex_id),
|
||||
},
|
||||
{
|
||||
.location = 7,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32_SFLOAT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanCrossFadeInstance, progress),
|
||||
}
|
||||
@ -98,27 +126,36 @@ gsk_vulkan_cross_fade_pipeline_new (GdkVulkanContext *context,
|
||||
return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_CROSS_FADE_PIPELINE, context, layout, shader_name, render_pass);
|
||||
}
|
||||
|
||||
gsize
|
||||
gsk_vulkan_cross_fade_pipeline_count_vertex_data (GskVulkanCrossFadePipeline *pipeline)
|
||||
{
|
||||
return sizeof (GskVulkanCrossFadeInstance);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_cross_fade_pipeline_collect_vertex_data (GskVulkanCrossFadePipeline *pipeline,
|
||||
guchar *data,
|
||||
const graphene_rect_t *bounds,
|
||||
const graphene_rect_t *start_tex_rect,
|
||||
const graphene_rect_t *end_tex_rect,
|
||||
double progress)
|
||||
guchar *data,
|
||||
guint32 start_tex_id[2],
|
||||
guint32 end_tex_id[2],
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *bounds,
|
||||
const graphene_rect_t *start_bounds,
|
||||
const graphene_rect_t *end_bounds,
|
||||
const graphene_rect_t *start_tex_rect,
|
||||
const graphene_rect_t *end_tex_rect,
|
||||
double progress)
|
||||
{
|
||||
GskVulkanCrossFadeInstance *instance = (GskVulkanCrossFadeInstance *) data;
|
||||
|
||||
instance->rect[0] = bounds->origin.x;
|
||||
instance->rect[1] = bounds->origin.y;
|
||||
instance->rect[0] = bounds->origin.x + offset->x;
|
||||
instance->rect[1] = bounds->origin.y + offset->y;
|
||||
instance->rect[2] = bounds->size.width;
|
||||
instance->rect[3] = bounds->size.height;
|
||||
|
||||
instance->start_rect[0] = start_bounds->origin.x + offset->x;
|
||||
instance->start_rect[1] = start_bounds->origin.y + offset->y;
|
||||
instance->start_rect[2] = start_bounds->size.width;
|
||||
instance->start_rect[3] = start_bounds->size.height;
|
||||
|
||||
instance->end_rect[0] = end_bounds->origin.x + offset->x;
|
||||
instance->end_rect[1] = end_bounds->origin.y + offset->y;
|
||||
instance->end_rect[2] = end_bounds->size.width;
|
||||
instance->end_rect[3] = end_bounds->size.height;
|
||||
|
||||
instance->start_tex_rect[0] = start_tex_rect->origin.x;
|
||||
instance->start_tex_rect[1] = start_tex_rect->origin.y;
|
||||
instance->start_tex_rect[2] = start_tex_rect->size.width;
|
||||
@ -129,6 +166,10 @@ gsk_vulkan_cross_fade_pipeline_collect_vertex_data (GskVulkanCrossFadePipeline *
|
||||
instance->end_tex_rect[2] = end_tex_rect->size.width;
|
||||
instance->end_tex_rect[3] = end_tex_rect->size.height;
|
||||
|
||||
instance->start_tex_id[0] = start_tex_id[0];
|
||||
instance->start_tex_id[1] = start_tex_id[1];
|
||||
instance->end_tex_id[0] = end_tex_id[0];
|
||||
instance->end_tex_id[1] = end_tex_id[1];
|
||||
instance->progress = progress;
|
||||
}
|
||||
|
||||
|
@ -17,12 +17,16 @@ GskVulkanPipeline * gsk_vulkan_cross_fade_pipeline_new (GdkVulka
|
||||
const char *shader_name,
|
||||
VkRenderPass render_pass);
|
||||
|
||||
gsize gsk_vulkan_cross_fade_pipeline_count_vertex_data (GskVulkanCrossFadePipeline *pipeline);
|
||||
void gsk_vulkan_cross_fade_pipeline_collect_vertex_data (GskVulkanCrossFadePipeline *pipeline,
|
||||
guchar *data,
|
||||
guint32 start_tex_id[2],
|
||||
guint32 end_tex_id[2],
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *bounds,
|
||||
const graphene_rect_t *start_bounds,
|
||||
const graphene_rect_t *end_bounds,
|
||||
const graphene_rect_t *start_tex_rect,
|
||||
const graphene_rect_t *end_tex_rect,
|
||||
double progress);
|
||||
gsize gsk_vulkan_cross_fade_pipeline_draw (GskVulkanCrossFadePipeline *pipeline,
|
||||
VkCommandBuffer command_buffer,
|
||||
|
@ -15,6 +15,7 @@ struct _GskVulkanEffectInstance
|
||||
float tex_rect[4];
|
||||
float color_matrix[16];
|
||||
float color_offset[4];
|
||||
guint32 tex_id[2];
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskVulkanEffectPipeline, gsk_vulkan_effect_pipeline, GSK_TYPE_VULKAN_PIPELINE)
|
||||
@ -71,6 +72,12 @@ gsk_vulkan_effect_pipeline_get_input_state_create_info (GskVulkanPipeline *self)
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanEffectInstance, color_offset),
|
||||
},
|
||||
{
|
||||
.location = 7,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_UINT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanEffectInstance, tex_id),
|
||||
}
|
||||
};
|
||||
static const VkPipelineVertexInputStateCreateInfo info = {
|
||||
@ -116,15 +123,11 @@ gsk_vulkan_effect_pipeline_new (GdkVulkanContext *context,
|
||||
return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_EFFECT_PIPELINE, context, layout, shader_name, render_pass);
|
||||
}
|
||||
|
||||
gsize
|
||||
gsk_vulkan_effect_pipeline_count_vertex_data (GskVulkanEffectPipeline *pipeline)
|
||||
{
|
||||
return sizeof (GskVulkanEffectInstance);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_effect_pipeline_collect_vertex_data (GskVulkanEffectPipeline *pipeline,
|
||||
guchar *data,
|
||||
guint32 tex_id[2],
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_rect_t *tex_rect,
|
||||
const graphene_matrix_t *color_matrix,
|
||||
@ -132,8 +135,8 @@ gsk_vulkan_effect_pipeline_collect_vertex_data (GskVulkanEffectPipeline *pipelin
|
||||
{
|
||||
GskVulkanEffectInstance *instance = (GskVulkanEffectInstance *) data;
|
||||
|
||||
instance->rect[0] = rect->origin.x;
|
||||
instance->rect[1] = rect->origin.y;
|
||||
instance->rect[0] = rect->origin.x + offset->x;
|
||||
instance->rect[1] = rect->origin.y + offset->y;
|
||||
instance->rect[2] = rect->size.width;
|
||||
instance->rect[3] = rect->size.height;
|
||||
instance->tex_rect[0] = tex_rect->origin.x;
|
||||
@ -142,6 +145,8 @@ gsk_vulkan_effect_pipeline_collect_vertex_data (GskVulkanEffectPipeline *pipelin
|
||||
instance->tex_rect[3] = tex_rect->size.height;
|
||||
graphene_matrix_to_float (color_matrix, instance->color_matrix);
|
||||
graphene_vec4_to_float (color_offset, instance->color_offset);
|
||||
instance->tex_id[0] = tex_id[0];
|
||||
instance->tex_id[1] = tex_id[1];
|
||||
}
|
||||
|
||||
gsize
|
||||
|
@ -17,9 +17,10 @@ GskVulkanPipeline * gsk_vulkan_effect_pipeline_new (GdkVulk
|
||||
const char *shader_name,
|
||||
VkRenderPass render_pass);
|
||||
|
||||
gsize gsk_vulkan_effect_pipeline_count_vertex_data (GskVulkanEffectPipeline *pipeline);
|
||||
void gsk_vulkan_effect_pipeline_collect_vertex_data (GskVulkanEffectPipeline *pipeline,
|
||||
guchar *data,
|
||||
guint32 tex_id[2],
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_rect_t *tex_rect,
|
||||
const graphene_matrix_t *color_matrix,
|
||||
|
@ -209,6 +209,8 @@ gsk_vulkan_image_new (GdkVulkanContext *context,
|
||||
VkMemoryRequirements requirements;
|
||||
GskVulkanImage *self;
|
||||
|
||||
g_assert (width > 0 && height > 0);
|
||||
|
||||
self = g_object_new (GSK_TYPE_VULKAN_IMAGE, NULL);
|
||||
|
||||
self->vulkan = g_object_ref (context);
|
||||
@ -606,9 +608,9 @@ gsk_vulkan_image_new_for_atlas (GdkVulkanContext *context,
|
||||
}
|
||||
|
||||
GskVulkanImage *
|
||||
gsk_vulkan_image_new_for_texture (GdkVulkanContext *context,
|
||||
gsize width,
|
||||
gsize height)
|
||||
gsk_vulkan_image_new_for_offscreen (GdkVulkanContext *context,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
GskVulkanImage *self;
|
||||
|
||||
@ -620,7 +622,7 @@ gsk_vulkan_image_new_for_texture (GdkVulkanContext *context,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
0,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
|
||||
|
@ -49,7 +49,7 @@ GskVulkanImage * gsk_vulkan_image_new_for_framebuffer (GdkVulk
|
||||
GskVulkanImage * gsk_vulkan_image_new_for_atlas (GdkVulkanContext *context,
|
||||
gsize width,
|
||||
gsize height);
|
||||
GskVulkanImage * gsk_vulkan_image_new_for_texture (GdkVulkanContext *context,
|
||||
GskVulkanImage * gsk_vulkan_image_new_for_offscreen (GdkVulkanContext *context,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
|
@ -167,15 +167,10 @@ gsk_vulkan_linear_gradient_pipeline_new (GdkVulkanContext *context,
|
||||
return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_LINEAR_GRADIENT_PIPELINE, context, layout, shader_name, render_pass);
|
||||
}
|
||||
|
||||
gsize
|
||||
gsk_vulkan_linear_gradient_pipeline_count_vertex_data (GskVulkanLinearGradientPipeline *pipeline)
|
||||
{
|
||||
return sizeof (GskVulkanLinearGradientInstance);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_linear_gradient_pipeline_collect_vertex_data (GskVulkanLinearGradientPipeline *pipeline,
|
||||
guchar *data,
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_point_t *start,
|
||||
const graphene_point_t *end,
|
||||
@ -191,14 +186,14 @@ gsk_vulkan_linear_gradient_pipeline_collect_vertex_data (GskVulkanLinearGradient
|
||||
g_warning ("Only %u color stops supported.", GSK_VULKAN_LINEAR_GRADIENT_PIPELINE_MAX_COLOR_STOPS);
|
||||
n_stops = GSK_VULKAN_LINEAR_GRADIENT_PIPELINE_MAX_COLOR_STOPS;
|
||||
}
|
||||
instance->rect[0] = rect->origin.x;
|
||||
instance->rect[1] = rect->origin.y;
|
||||
instance->rect[0] = rect->origin.x + offset->x;
|
||||
instance->rect[1] = rect->origin.y + offset->y;
|
||||
instance->rect[2] = rect->size.width;
|
||||
instance->rect[3] = rect->size.height;
|
||||
instance->start[0] = start->x;
|
||||
instance->start[1] = start->y;
|
||||
instance->end[0] = end->x;
|
||||
instance->end[1] = end->y;
|
||||
instance->start[0] = start->x + offset->x;
|
||||
instance->start[1] = start->y + offset->y;
|
||||
instance->end[0] = end->x + offset->x;
|
||||
instance->end[1] = end->y + offset->y;
|
||||
instance->repeating = repeating;
|
||||
instance->stop_count = n_stops;
|
||||
for (i = 0; i < n_stops; i++)
|
||||
|
@ -20,11 +20,10 @@ GskVulkanPipeline * gsk_vulkan_linear_gradient_pipeline_new (GdkVulk
|
||||
const char *shader_name,
|
||||
VkRenderPass render_pass);
|
||||
|
||||
gsize gsk_vulkan_linear_gradient_pipeline_count_vertex_data
|
||||
(GskVulkanLinearGradientPipeline*pipeline);
|
||||
void gsk_vulkan_linear_gradient_pipeline_collect_vertex_data
|
||||
(GskVulkanLinearGradientPipeline*pipeline,
|
||||
guchar *data,
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_point_t *start,
|
||||
const graphene_point_t *end,
|
||||
|
@ -16,10 +16,11 @@ struct _GskVulkanPipelinePrivate
|
||||
GdkVulkanContext *context;
|
||||
|
||||
VkPipeline pipeline;
|
||||
VkPipelineLayout layout;
|
||||
|
||||
GskVulkanShader *vertex_shader;
|
||||
GskVulkanShader *fragment_shader;
|
||||
|
||||
gsize vertex_stride;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GskVulkanPipeline, gsk_vulkan_pipeline, G_TYPE_OBJECT)
|
||||
@ -54,12 +55,13 @@ gsk_vulkan_pipeline_init (GskVulkanPipeline *self)
|
||||
}
|
||||
|
||||
GskVulkanPipeline *
|
||||
gsk_vulkan_pipeline_new (GType pipeline_type,
|
||||
GdkVulkanContext *context,
|
||||
VkPipelineLayout layout,
|
||||
const char *shader_name,
|
||||
VkRenderPass render_pass)
|
||||
gsk_vulkan_pipeline_new (GType pipeline_type,
|
||||
GdkVulkanContext *context,
|
||||
VkPipelineLayout layout,
|
||||
const char *shader_name,
|
||||
VkRenderPass render_pass)
|
||||
{
|
||||
const VkPipelineVertexInputStateCreateInfo *vertex_input_state;
|
||||
GskVulkanPipelinePrivate *priv;
|
||||
GskVulkanPipeline *self;
|
||||
VkDevice device;
|
||||
@ -76,11 +78,14 @@ gsk_vulkan_pipeline_new (GType pipeline_type,
|
||||
device = gdk_vulkan_context_get_device (context);
|
||||
|
||||
priv->context = context;
|
||||
priv->layout = layout;
|
||||
|
||||
priv->vertex_shader = gsk_vulkan_shader_new_from_resource (context, GSK_VULKAN_SHADER_VERTEX, shader_name, NULL);
|
||||
priv->fragment_shader = gsk_vulkan_shader_new_from_resource (context, GSK_VULKAN_SHADER_FRAGMENT, shader_name, NULL);
|
||||
|
||||
vertex_input_state = GSK_VULKAN_PIPELINE_GET_CLASS (self)->get_input_state_create_info (self);
|
||||
g_assert (vertex_input_state->vertexBindingDescriptionCount == 1);
|
||||
priv->vertex_stride = vertex_input_state->pVertexBindingDescriptions[0].stride;
|
||||
|
||||
GSK_VK_CHECK (vkCreateGraphicsPipelines, device,
|
||||
VK_NULL_HANDLE,
|
||||
1,
|
||||
@ -91,7 +96,7 @@ gsk_vulkan_pipeline_new (GType pipeline_type,
|
||||
GST_VULKAN_SHADER_STAGE_CREATE_INFO (priv->vertex_shader),
|
||||
GST_VULKAN_SHADER_STAGE_CREATE_INFO (priv->fragment_shader)
|
||||
},
|
||||
.pVertexInputState = GSK_VULKAN_PIPELINE_GET_CLASS (self)->get_input_state_create_info (self),
|
||||
.pVertexInputState = vertex_input_state,
|
||||
.pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
||||
@ -108,7 +113,7 @@ gsk_vulkan_pipeline_new (GType pipeline_type,
|
||||
.depthClampEnable = VK_FALSE,
|
||||
.rasterizerDiscardEnable = VK_FALSE,
|
||||
.polygonMode = VK_POLYGON_MODE_FILL,
|
||||
.cullMode = VK_CULL_MODE_BACK_BIT,
|
||||
.cullMode = VK_CULL_MODE_NONE,
|
||||
.frontFace = VK_FRONT_FACE_CLOCKWISE,
|
||||
.lineWidth = 1.0f,
|
||||
},
|
||||
@ -146,7 +151,7 @@ gsk_vulkan_pipeline_new (GType pipeline_type,
|
||||
VK_DYNAMIC_STATE_SCISSOR
|
||||
},
|
||||
},
|
||||
.layout = priv->layout,
|
||||
.layout = layout,
|
||||
.renderPass = render_pass,
|
||||
.subpass = 0,
|
||||
.basePipelineHandle = VK_NULL_HANDLE,
|
||||
@ -166,10 +171,10 @@ gsk_vulkan_pipeline_get_pipeline (GskVulkanPipeline *self)
|
||||
return priv->pipeline;
|
||||
}
|
||||
|
||||
VkPipelineLayout
|
||||
gsk_vulkan_pipeline_get_pipeline_layout (GskVulkanPipeline *self)
|
||||
gsize
|
||||
gsk_vulkan_pipeline_get_vertex_stride (GskVulkanPipeline *self)
|
||||
{
|
||||
GskVulkanPipelinePrivate *priv = gsk_vulkan_pipeline_get_instance_private (self);
|
||||
|
||||
return priv->layout;
|
||||
return priv->vertex_stride;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ GskVulkanPipeline * gsk_vulkan_pipeline_new (GType
|
||||
const char *shader_name,
|
||||
VkRenderPass render_pass);
|
||||
VkPipeline gsk_vulkan_pipeline_get_pipeline (GskVulkanPipeline *self);
|
||||
VkPipelineLayout gsk_vulkan_pipeline_get_pipeline_layout (GskVulkanPipeline *self);
|
||||
gsize gsk_vulkan_pipeline_get_vertex_stride (GskVulkanPipeline *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -12,83 +12,37 @@ struct _GskVulkanPushConstantsWire
|
||||
struct {
|
||||
float mvp[16];
|
||||
float clip[12];
|
||||
float scale[2];
|
||||
} common;
|
||||
};
|
||||
|
||||
void
|
||||
gsk_vulkan_push_constants_init (GskVulkanPushConstants *constants,
|
||||
const graphene_matrix_t *mvp,
|
||||
const graphene_rect_t *viewport)
|
||||
{
|
||||
graphene_matrix_init_from_matrix (&constants->mvp, mvp);
|
||||
gsk_vulkan_clip_init_empty (&constants->clip, viewport);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_push_constants_init_copy (GskVulkanPushConstants *self,
|
||||
const GskVulkanPushConstants *src)
|
||||
{
|
||||
*self = *src;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gsk_vulkan_push_constants_transform (GskVulkanPushConstants *self,
|
||||
const GskVulkanPushConstants *src,
|
||||
GskTransform *transform,
|
||||
const graphene_rect_t *viewport)
|
||||
|
||||
{
|
||||
graphene_matrix_t matrix;
|
||||
|
||||
if (!gsk_vulkan_clip_transform (&self->clip, &src->clip, transform, viewport))
|
||||
return FALSE;
|
||||
|
||||
gsk_transform_to_matrix (transform, &matrix);
|
||||
graphene_matrix_multiply (&matrix, &src->mvp, &self->mvp);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gsk_vulkan_push_constants_intersect_rect (GskVulkanPushConstants *self,
|
||||
const GskVulkanPushConstants *src,
|
||||
const graphene_rect_t *rect)
|
||||
{
|
||||
if (!gsk_vulkan_clip_intersect_rect (&self->clip, &src->clip, rect))
|
||||
return FALSE;
|
||||
|
||||
graphene_matrix_init_from_matrix (&self->mvp, &src->mvp);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gsk_vulkan_push_constants_intersect_rounded (GskVulkanPushConstants *self,
|
||||
const GskVulkanPushConstants *src,
|
||||
const GskRoundedRect *rect)
|
||||
{
|
||||
if (!gsk_vulkan_clip_intersect_rounded_rect (&self->clip, &src->clip, rect))
|
||||
return FALSE;
|
||||
|
||||
graphene_matrix_init_from_matrix (&self->mvp, &src->mvp);
|
||||
return TRUE;
|
||||
}
|
||||
/* This is the value we know every conformant GPU must provide.
|
||||
* See value for maxPushConstantsSize in table 55 of
|
||||
* https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#limits-minmax
|
||||
*/
|
||||
G_STATIC_ASSERT (sizeof (GskVulkanPushConstantsWire) <= 128);
|
||||
|
||||
static void
|
||||
gsk_vulkan_push_constants_wire_init (GskVulkanPushConstantsWire *wire,
|
||||
const GskVulkanPushConstants *self)
|
||||
gsk_vulkan_push_constants_wire_init (GskVulkanPushConstantsWire *wire,
|
||||
const graphene_vec2_t *scale,
|
||||
const graphene_matrix_t *mvp,
|
||||
const GskRoundedRect *clip)
|
||||
{
|
||||
graphene_matrix_to_float (&self->mvp, wire->common.mvp);
|
||||
gsk_rounded_rect_to_float (&self->clip.rect, wire->common.clip);
|
||||
graphene_matrix_to_float (mvp, wire->common.mvp);
|
||||
gsk_rounded_rect_to_float (clip, graphene_point_zero (), wire->common.clip);
|
||||
graphene_vec2_to_float (scale, wire->common.scale);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_push_constants_push (const GskVulkanPushConstants *self,
|
||||
VkCommandBuffer command_buffer,
|
||||
VkPipelineLayout pipeline_layout)
|
||||
gsk_vulkan_push_constants_push (VkCommandBuffer command_buffer,
|
||||
VkPipelineLayout pipeline_layout,
|
||||
const graphene_vec2_t *scale,
|
||||
const graphene_matrix_t *mvp,
|
||||
const GskRoundedRect *clip)
|
||||
{
|
||||
GskVulkanPushConstantsWire wire;
|
||||
|
||||
gsk_vulkan_push_constants_wire_init (&wire, self);
|
||||
gsk_vulkan_push_constants_wire_init (&wire, scale, mvp, clip);
|
||||
|
||||
vkCmdPushConstants (command_buffer,
|
||||
pipeline_layout,
|
||||
|
@ -6,38 +6,15 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GskVulkanPushConstants GskVulkanPushConstants;
|
||||
|
||||
struct _GskVulkanPushConstants
|
||||
{
|
||||
graphene_matrix_t mvp;
|
||||
GskVulkanClip clip;
|
||||
};
|
||||
|
||||
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_init (GskVulkanPushConstants *constants,
|
||||
void gsk_vulkan_push_constants_push (VkCommandBuffer command_buffer,
|
||||
VkPipelineLayout pipeline_layout,
|
||||
const graphene_vec2_t *scale,
|
||||
const graphene_matrix_t *mvp,
|
||||
const graphene_rect_t *viewport);
|
||||
void gsk_vulkan_push_constants_init_copy (GskVulkanPushConstants *self,
|
||||
const GskVulkanPushConstants *src);
|
||||
|
||||
gboolean gsk_vulkan_push_constants_transform (GskVulkanPushConstants *self,
|
||||
const GskVulkanPushConstants *src,
|
||||
GskTransform *transform,
|
||||
const graphene_rect_t *viewport);
|
||||
gboolean gsk_vulkan_push_constants_intersect_rect (GskVulkanPushConstants *self,
|
||||
const GskVulkanPushConstants *src,
|
||||
const graphene_rect_t *rect);
|
||||
gboolean gsk_vulkan_push_constants_intersect_rounded (GskVulkanPushConstants *self,
|
||||
const GskVulkanPushConstants *src,
|
||||
const GskRoundedRect *rect);
|
||||
|
||||
void gsk_vulkan_push_constants_push (const GskVulkanPushConstants *self,
|
||||
VkCommandBuffer command_buffer,
|
||||
VkPipelineLayout pipeline_layout);
|
||||
const GskRoundedRect *clip);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -23,8 +23,15 @@
|
||||
#include "gskvulkantexturepipelineprivate.h"
|
||||
#include "gskvulkanpushconstantsprivate.h"
|
||||
|
||||
#define DESCRIPTOR_POOL_MAXSETS 128
|
||||
#define DESCRIPTOR_POOL_MAXSETS_INCREASE 128
|
||||
#define DESCRIPTOR_POOL_MAXITEMS 50000
|
||||
|
||||
#define GDK_ARRAY_NAME gsk_descriptor_image_infos
|
||||
#define GDK_ARRAY_TYPE_NAME GskDescriptorImageInfos
|
||||
#define GDK_ARRAY_ELEMENT_TYPE VkDescriptorImageInfo
|
||||
#define GDK_ARRAY_BY_VALUE 1
|
||||
#define GDK_ARRAY_PREALLOC 1024
|
||||
#define GDK_ARRAY_NO_MEMSET 1
|
||||
#include "gdk/gdkarrayimpl.c"
|
||||
|
||||
struct _GskVulkanRender
|
||||
{
|
||||
@ -40,20 +47,18 @@ struct _GskVulkanRender
|
||||
VkFence fence;
|
||||
VkRenderPass render_pass;
|
||||
VkDescriptorSetLayout descriptor_set_layout;
|
||||
VkPipelineLayout pipeline_layout[3]; /* indexed by number of textures */
|
||||
VkPipelineLayout pipeline_layout;
|
||||
GskVulkanUploader *uploader;
|
||||
|
||||
GHashTable *descriptor_set_indexes;
|
||||
GskDescriptorImageInfos descriptor_images;
|
||||
GskDescriptorImageInfos descriptor_samplers;
|
||||
VkDescriptorPool descriptor_pool;
|
||||
uint32_t descriptor_pool_maxsets;
|
||||
VkDescriptorSet *descriptor_sets;
|
||||
gsize n_descriptor_sets;
|
||||
VkDescriptorSet descriptor_set;
|
||||
GskVulkanPipeline *pipelines[GSK_VULKAN_N_PIPELINES];
|
||||
|
||||
GskVulkanImage *target;
|
||||
|
||||
VkSampler sampler;
|
||||
VkSampler repeating_sampler;
|
||||
VkSampler samplers[3];
|
||||
|
||||
GList *render_passes;
|
||||
GSList *cleanup_images;
|
||||
@ -103,9 +108,6 @@ gsk_vulkan_render_setup (GskVulkanRender *self,
|
||||
}
|
||||
}
|
||||
|
||||
static guint desc_set_index_hash (gconstpointer v);
|
||||
static gboolean desc_set_index_equal (gconstpointer v1, gconstpointer v2);
|
||||
|
||||
GskVulkanRender *
|
||||
gsk_vulkan_render_new (GskRenderer *renderer,
|
||||
GdkVulkanContext *context)
|
||||
@ -118,7 +120,8 @@ gsk_vulkan_render_new (GskRenderer *renderer,
|
||||
self->vulkan = context;
|
||||
self->renderer = renderer;
|
||||
self->framebuffers = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
self->descriptor_set_indexes = g_hash_table_new_full (desc_set_index_hash, desc_set_index_equal, NULL, g_free);
|
||||
gsk_descriptor_image_infos_init (&self->descriptor_images);
|
||||
gsk_descriptor_image_infos_init (&self->descriptor_samplers);
|
||||
|
||||
device = gdk_vulkan_context_get_device (self->vulkan);
|
||||
|
||||
@ -131,16 +134,20 @@ gsk_vulkan_render_new (GskRenderer *renderer,
|
||||
NULL,
|
||||
&self->fence);
|
||||
|
||||
self->descriptor_pool_maxsets = DESCRIPTOR_POOL_MAXSETS;
|
||||
GSK_VK_CHECK (vkCreateDescriptorPool, device,
|
||||
&(VkDescriptorPoolCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.maxSets = self->descriptor_pool_maxsets,
|
||||
.poolSizeCount = 1,
|
||||
.pPoolSizes = (VkDescriptorPoolSize[1]) {
|
||||
.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT,
|
||||
.maxSets = 1,
|
||||
.poolSizeCount = 2,
|
||||
.pPoolSizes = (VkDescriptorPoolSize[2]) {
|
||||
{
|
||||
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = self->descriptor_pool_maxsets
|
||||
.type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
.descriptorCount = DESCRIPTOR_POOL_MAXITEMS
|
||||
},
|
||||
{
|
||||
.type = VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||
.descriptorCount = DESCRIPTOR_POOL_MAXITEMS
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -190,53 +197,65 @@ gsk_vulkan_render_new (GskRenderer *renderer,
|
||||
GSK_VK_CHECK (vkCreateDescriptorSetLayout, device,
|
||||
&(VkDescriptorSetLayoutCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.bindingCount = 1,
|
||||
.pBindings = (VkDescriptorSetLayoutBinding[1]) {
|
||||
.bindingCount = 2,
|
||||
.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
|
||||
.pBindings = (VkDescriptorSetLayoutBinding[2]) {
|
||||
{
|
||||
.binding = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
.descriptorCount = DESCRIPTOR_POOL_MAXITEMS,
|
||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
|
||||
},
|
||||
{
|
||||
.binding = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||
.descriptorCount = DESCRIPTOR_POOL_MAXITEMS,
|
||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
|
||||
}
|
||||
},
|
||||
.pNext = &(VkDescriptorSetLayoutBindingFlagsCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
|
||||
.bindingCount = 2,
|
||||
.pBindingFlags = (VkDescriptorBindingFlags[2]) {
|
||||
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT
|
||||
| VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT
|
||||
| VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
|
||||
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT
|
||||
| VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT
|
||||
| VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
|
||||
},
|
||||
}
|
||||
},
|
||||
NULL,
|
||||
&self->descriptor_set_layout);
|
||||
|
||||
for (guint i = 0; i < 3; i++)
|
||||
{
|
||||
VkDescriptorSetLayout layouts[3] = {
|
||||
self->descriptor_set_layout,
|
||||
self->descriptor_set_layout,
|
||||
self->descriptor_set_layout
|
||||
};
|
||||
|
||||
GSK_VK_CHECK (vkCreatePipelineLayout, device,
|
||||
&(VkPipelineLayoutCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.setLayoutCount = i,
|
||||
.pSetLayouts = layouts,
|
||||
.pushConstantRangeCount = gsk_vulkan_push_constants_get_range_count (),
|
||||
.pPushConstantRanges = gsk_vulkan_push_constants_get_ranges ()
|
||||
GSK_VK_CHECK (vkCreatePipelineLayout, device,
|
||||
&(VkPipelineLayoutCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.setLayoutCount = 1,
|
||||
.pSetLayouts = (VkDescriptorSetLayout[1]) {
|
||||
self->descriptor_set_layout
|
||||
},
|
||||
NULL,
|
||||
&self->pipeline_layout[i]);
|
||||
}
|
||||
.pushConstantRangeCount = gsk_vulkan_push_constants_get_range_count (),
|
||||
.pPushConstantRanges = gsk_vulkan_push_constants_get_ranges ()
|
||||
},
|
||||
NULL,
|
||||
&self->pipeline_layout);
|
||||
|
||||
GSK_VK_CHECK (vkCreateSampler, device,
|
||||
&(VkSamplerCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
.magFilter = VK_FILTER_LINEAR,
|
||||
.minFilter = VK_FILTER_LINEAR,
|
||||
.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
|
||||
.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
|
||||
.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||
.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
|
||||
.unnormalizedCoordinates = VK_FALSE,
|
||||
.maxAnisotropy = 1.0,
|
||||
},
|
||||
NULL,
|
||||
&self->sampler);
|
||||
&self->samplers[GSK_VULKAN_SAMPLER_DEFAULT]);
|
||||
|
||||
GSK_VK_CHECK (vkCreateSampler, device,
|
||||
&(VkSamplerCreateInfo) {
|
||||
@ -251,7 +270,23 @@ gsk_vulkan_render_new (GskRenderer *renderer,
|
||||
.maxAnisotropy = 1.0,
|
||||
},
|
||||
NULL,
|
||||
&self->repeating_sampler);
|
||||
&self->samplers[GSK_VULKAN_SAMPLER_REPEAT]);
|
||||
|
||||
GSK_VK_CHECK (vkCreateSampler, device,
|
||||
&(VkSamplerCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
.magFilter = VK_FILTER_NEAREST,
|
||||
.minFilter = VK_FILTER_NEAREST,
|
||||
.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||
.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
|
||||
.unnormalizedCoordinates = VK_FALSE,
|
||||
.maxAnisotropy = 1.0,
|
||||
},
|
||||
NULL,
|
||||
&self->samplers[GSK_VULKAN_SAMPLER_NEAREST]);
|
||||
|
||||
|
||||
self->uploader = gsk_vulkan_uploader_new (self->vulkan, self->command_pool);
|
||||
|
||||
@ -315,6 +350,12 @@ gsk_vulkan_render_get_framebuffer (GskVulkanRender *self,
|
||||
return fb->framebuffer;
|
||||
}
|
||||
|
||||
VkFence
|
||||
gsk_vulkan_render_get_fence (GskVulkanRender *self)
|
||||
{
|
||||
return self->fence;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_render_add_cleanup_image (GskVulkanRender *self,
|
||||
GskVulkanImage *image)
|
||||
@ -338,15 +379,13 @@ gsk_vulkan_render_add_node (GskVulkanRender *self,
|
||||
GskRenderNode *node)
|
||||
{
|
||||
GskVulkanRenderPass *pass;
|
||||
graphene_matrix_t mv;
|
||||
graphene_vec2_t scale;
|
||||
|
||||
graphene_matrix_init_scale (&mv, self->scale, self->scale, 1.0);
|
||||
graphene_vec2_init (&scale, self->scale, self->scale);
|
||||
|
||||
pass = gsk_vulkan_render_pass_new (self->vulkan,
|
||||
self->target,
|
||||
self->scale,
|
||||
self->scale,
|
||||
&mv,
|
||||
&scale,
|
||||
&self->viewport,
|
||||
self->clip,
|
||||
VK_NULL_HANDLE);
|
||||
@ -425,7 +464,7 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender *self,
|
||||
|
||||
if (self->pipelines[type] == NULL)
|
||||
self->pipelines[type] = pipeline_info[type].create_func (self->vulkan,
|
||||
self->pipeline_layout[pipeline_info[type].num_textures],
|
||||
self->pipeline_layout,
|
||||
pipeline_info[type].name,
|
||||
self->render_pass);
|
||||
|
||||
@ -433,71 +472,59 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender *self,
|
||||
}
|
||||
|
||||
VkDescriptorSet
|
||||
gsk_vulkan_render_get_descriptor_set (GskVulkanRender *self,
|
||||
gsize id)
|
||||
gsk_vulkan_render_get_descriptor_set (GskVulkanRender *self)
|
||||
{
|
||||
g_assert (id < self->n_descriptor_sets);
|
||||
|
||||
return self->descriptor_sets[id];
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
gsize index;
|
||||
GskVulkanImage *image;
|
||||
gboolean repeat;
|
||||
} HashDescriptorSetIndexEntry;
|
||||
|
||||
static guint
|
||||
desc_set_index_hash (gconstpointer v)
|
||||
{
|
||||
const HashDescriptorSetIndexEntry *e = v;
|
||||
|
||||
return GPOINTER_TO_UINT (e->image) + e->repeat;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
desc_set_index_equal (gconstpointer v1, gconstpointer v2)
|
||||
{
|
||||
const HashDescriptorSetIndexEntry *e1 = v1;
|
||||
const HashDescriptorSetIndexEntry *e2 = v2;
|
||||
|
||||
return e1->image == e2->image && e1->repeat == e2->repeat;
|
||||
return self->descriptor_set;
|
||||
}
|
||||
|
||||
gsize
|
||||
gsk_vulkan_render_reserve_descriptor_set (GskVulkanRender *self,
|
||||
GskVulkanImage *source,
|
||||
gboolean repeat)
|
||||
gsk_vulkan_render_get_sampler_descriptor (GskVulkanRender *self,
|
||||
GskVulkanRenderSampler render_sampler)
|
||||
{
|
||||
HashDescriptorSetIndexEntry lookup;
|
||||
HashDescriptorSetIndexEntry *entry;
|
||||
VkSampler sampler = self->samplers[render_sampler];
|
||||
gsize i;
|
||||
|
||||
g_assert (source != NULL);
|
||||
/* If this ever shows up in profiles, add a hash table */
|
||||
for (i = 0; i < gsk_descriptor_image_infos_get_size (&self->descriptor_samplers); i++)
|
||||
{
|
||||
if (gsk_descriptor_image_infos_get (&self->descriptor_samplers, i)->sampler == sampler)
|
||||
return i;
|
||||
}
|
||||
|
||||
lookup.image = source;
|
||||
lookup.repeat = repeat;
|
||||
g_assert (i < DESCRIPTOR_POOL_MAXITEMS);
|
||||
|
||||
entry = g_hash_table_lookup (self->descriptor_set_indexes, &lookup);
|
||||
if (entry)
|
||||
return entry->index;
|
||||
gsk_descriptor_image_infos_append (&self->descriptor_samplers,
|
||||
&(VkDescriptorImageInfo) {
|
||||
.sampler = sampler,
|
||||
});
|
||||
|
||||
entry = g_new (HashDescriptorSetIndexEntry, 1);
|
||||
entry->image = source;
|
||||
entry->repeat = repeat;
|
||||
entry->index = g_hash_table_size (self->descriptor_set_indexes);
|
||||
g_hash_table_add (self->descriptor_set_indexes, entry);
|
||||
return i;
|
||||
}
|
||||
|
||||
return entry->index;
|
||||
gsize
|
||||
gsk_vulkan_render_get_image_descriptor (GskVulkanRender *self,
|
||||
GskVulkanImage *image)
|
||||
{
|
||||
gsize result;
|
||||
|
||||
result = gsk_descriptor_image_infos_get_size (&self->descriptor_images);
|
||||
gsk_descriptor_image_infos_append (&self->descriptor_images,
|
||||
&(VkDescriptorImageInfo) {
|
||||
.sampler = VK_NULL_HANDLE,
|
||||
.imageView = gsk_vulkan_image_get_image_view (image),
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
});
|
||||
|
||||
g_assert (result < DESCRIPTOR_POOL_MAXITEMS);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_render_prepare_descriptor_sets (GskVulkanRender *self)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer key;
|
||||
VkDevice device;
|
||||
GList *l;
|
||||
guint i, needed_sets;
|
||||
|
||||
device = gdk_vulkan_context_get_device (self->vulkan);
|
||||
|
||||
@ -507,85 +534,50 @@ gsk_vulkan_render_prepare_descriptor_sets (GskVulkanRender *self)
|
||||
gsk_vulkan_render_pass_reserve_descriptor_sets (pass, self);
|
||||
}
|
||||
|
||||
needed_sets = g_hash_table_size (self->descriptor_set_indexes);
|
||||
if (needed_sets > self->n_descriptor_sets)
|
||||
{
|
||||
if (needed_sets > self->descriptor_pool_maxsets)
|
||||
{
|
||||
guint added_sets = needed_sets - self->descriptor_pool_maxsets;
|
||||
added_sets = added_sets + DESCRIPTOR_POOL_MAXSETS_INCREASE - 1;
|
||||
added_sets -= added_sets % DESCRIPTOR_POOL_MAXSETS_INCREASE;
|
||||
|
||||
vkDestroyDescriptorPool (device,
|
||||
self->descriptor_pool,
|
||||
NULL);
|
||||
self->descriptor_pool_maxsets += added_sets;
|
||||
GSK_VK_CHECK (vkCreateDescriptorPool, device,
|
||||
&(VkDescriptorPoolCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.maxSets = self->descriptor_pool_maxsets,
|
||||
.poolSizeCount = 1,
|
||||
.pPoolSizes = (VkDescriptorPoolSize[1]) {
|
||||
{
|
||||
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = self->descriptor_pool_maxsets
|
||||
}
|
||||
}
|
||||
},
|
||||
NULL,
|
||||
&self->descriptor_pool);
|
||||
}
|
||||
else
|
||||
{
|
||||
GSK_VK_CHECK (vkResetDescriptorPool, device,
|
||||
self->descriptor_pool,
|
||||
0);
|
||||
}
|
||||
|
||||
self->n_descriptor_sets = needed_sets;
|
||||
self->descriptor_sets = g_renew (VkDescriptorSet, self->descriptor_sets, needed_sets);
|
||||
}
|
||||
|
||||
VkDescriptorSetLayout *layouts = g_newa (VkDescriptorSetLayout, needed_sets);
|
||||
for (i = 0; i < needed_sets; i++)
|
||||
layouts[i] = self->descriptor_set_layout;
|
||||
if (gsk_descriptor_image_infos_get_size (&self->descriptor_samplers) == 0 &&
|
||||
gsk_descriptor_image_infos_get_size (&self->descriptor_images) == 0)
|
||||
return;
|
||||
|
||||
GSK_VK_CHECK (vkAllocateDescriptorSets, device,
|
||||
&(VkDescriptorSetAllocateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.descriptorPool = self->descriptor_pool,
|
||||
.descriptorSetCount = needed_sets,
|
||||
.pSetLayouts = layouts
|
||||
.descriptorSetCount = 1,
|
||||
.pSetLayouts = &self->descriptor_set_layout,
|
||||
.pNext = &(VkDescriptorSetVariableDescriptorCountAllocateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO,
|
||||
.descriptorSetCount = 1,
|
||||
.pDescriptorCounts = (uint32_t[1]) {
|
||||
gsk_descriptor_image_infos_get_size (&self->descriptor_images)
|
||||
+ gsk_descriptor_image_infos_get_size (&self->descriptor_samplers)
|
||||
}
|
||||
}
|
||||
},
|
||||
self->descriptor_sets);
|
||||
&self->descriptor_set);
|
||||
|
||||
g_hash_table_iter_init (&iter, self->descriptor_set_indexes);
|
||||
while (g_hash_table_iter_next (&iter, &key, NULL))
|
||||
{
|
||||
HashDescriptorSetIndexEntry *entry = key;
|
||||
GskVulkanImage *image = entry->image;
|
||||
gsize id = entry->index;
|
||||
gboolean repeat = entry->repeat;
|
||||
|
||||
vkUpdateDescriptorSets (device,
|
||||
1,
|
||||
(VkWriteDescriptorSet[1]) {
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = self->descriptor_sets[id],
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.pImageInfo = &(VkDescriptorImageInfo) {
|
||||
.sampler = repeat ? self->repeating_sampler : self->sampler,
|
||||
.imageView = gsk_vulkan_image_get_image_view (image),
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
}
|
||||
}
|
||||
vkUpdateDescriptorSets (device,
|
||||
2,
|
||||
(VkWriteDescriptorSet[2]) {
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = self->descriptor_set,
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = gsk_descriptor_image_infos_get_size (&self->descriptor_images),
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
.pImageInfo = gsk_descriptor_image_infos_get_data (&self->descriptor_images)
|
||||
},
|
||||
0, NULL);
|
||||
}
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = self->descriptor_set,
|
||||
.dstBinding = 1,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = gsk_descriptor_image_infos_get_size (&self->descriptor_samplers),
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||
.pImageInfo = gsk_descriptor_image_infos_get_data (&self->descriptor_samplers)
|
||||
}
|
||||
},
|
||||
0, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
@ -614,7 +606,7 @@ gsk_vulkan_render_draw (GskVulkanRender *self)
|
||||
|
||||
command_buffer = gsk_vulkan_command_pool_get_buffer (self->command_pool);
|
||||
|
||||
gsk_vulkan_render_pass_draw (pass, self, 3, self->pipeline_layout, command_buffer);
|
||||
gsk_vulkan_render_pass_draw (pass, self, self->pipeline_layout, command_buffer);
|
||||
|
||||
gsk_vulkan_command_pool_submit_buffer (self->command_pool,
|
||||
command_buffer,
|
||||
@ -675,10 +667,11 @@ gsk_vulkan_render_cleanup (GskVulkanRender *self)
|
||||
|
||||
gsk_vulkan_command_pool_reset (self->command_pool);
|
||||
|
||||
g_hash_table_remove_all (self->descriptor_set_indexes);
|
||||
GSK_VK_CHECK (vkResetDescriptorPool, device,
|
||||
self->descriptor_pool,
|
||||
0);
|
||||
gsk_descriptor_image_infos_set_size (&self->descriptor_images, 0);
|
||||
gsk_descriptor_image_infos_set_size (&self->descriptor_samplers, 0);
|
||||
|
||||
g_list_free_full (self->render_passes, (GDestroyNotify) gsk_vulkan_render_pass_free);
|
||||
self->render_passes = NULL;
|
||||
@ -720,10 +713,10 @@ gsk_vulkan_render_free (GskVulkanRender *self)
|
||||
|
||||
g_clear_pointer (&self->uploader, gsk_vulkan_uploader_free);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
vkDestroyPipelineLayout (device,
|
||||
self->pipeline_layout[i],
|
||||
NULL);
|
||||
|
||||
vkDestroyPipelineLayout (device,
|
||||
self->pipeline_layout,
|
||||
NULL);
|
||||
|
||||
vkDestroyRenderPass (device,
|
||||
self->render_pass,
|
||||
@ -732,8 +725,8 @@ gsk_vulkan_render_free (GskVulkanRender *self)
|
||||
vkDestroyDescriptorPool (device,
|
||||
self->descriptor_pool,
|
||||
NULL);
|
||||
g_free (self->descriptor_sets);
|
||||
g_hash_table_unref (self->descriptor_set_indexes);
|
||||
gsk_descriptor_image_infos_clear (&self->descriptor_images);
|
||||
gsk_descriptor_image_infos_clear (&self->descriptor_samplers);
|
||||
|
||||
vkDestroyDescriptorSetLayout (device,
|
||||
self->descriptor_set_layout,
|
||||
@ -743,13 +736,12 @@ gsk_vulkan_render_free (GskVulkanRender *self)
|
||||
self->fence,
|
||||
NULL);
|
||||
|
||||
vkDestroySampler (device,
|
||||
self->sampler,
|
||||
NULL);
|
||||
|
||||
vkDestroySampler (device,
|
||||
self->repeating_sampler,
|
||||
NULL);
|
||||
for (i = 0; i < G_N_ELEMENTS (self->samplers); i++)
|
||||
{
|
||||
vkDestroySampler (device,
|
||||
self->samplers[i],
|
||||
NULL);
|
||||
}
|
||||
|
||||
gsk_vulkan_command_pool_free (self->command_pool);
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
#include <graphene.h>
|
||||
|
||||
#define GSK_VULKAN_MAX_RENDERS 4
|
||||
|
||||
typedef struct _GskVulkanTextureData GskVulkanTextureData;
|
||||
|
||||
struct _GskVulkanTextureData {
|
||||
@ -51,7 +53,7 @@ struct _GskVulkanRenderer
|
||||
guint n_targets;
|
||||
GskVulkanImage **targets;
|
||||
|
||||
GskVulkanRender *render;
|
||||
GskVulkanRender *renders[GSK_VULKAN_MAX_RENDERS];
|
||||
|
||||
GSList *textures;
|
||||
|
||||
@ -161,6 +163,38 @@ gsk_vulkan_renderer_update_images_cb (GdkVulkanContext *context,
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
@ -185,8 +219,6 @@ gsk_vulkan_renderer_realize (GskRenderer *renderer,
|
||||
self);
|
||||
gsk_vulkan_renderer_update_images_cb (self->vulkan, self);
|
||||
|
||||
self->render = gsk_vulkan_render_new (renderer, self->vulkan);
|
||||
|
||||
self->glyph_cache = gsk_vulkan_glyph_cache_new (renderer, self->vulkan);
|
||||
|
||||
return TRUE;
|
||||
@ -197,6 +229,7 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer)
|
||||
{
|
||||
GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
|
||||
GSList *l;
|
||||
guint i;
|
||||
|
||||
g_clear_object (&self->glyph_cache);
|
||||
|
||||
@ -209,7 +242,8 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer)
|
||||
}
|
||||
g_clear_pointer (&self->textures, g_slist_free);
|
||||
|
||||
g_clear_pointer (&self->render, gsk_vulkan_render_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,
|
||||
@ -228,6 +262,7 @@ gsk_vulkan_renderer_render_texture (GskRenderer *renderer,
|
||||
GskVulkanRender *render;
|
||||
GskVulkanImage *image;
|
||||
GdkTexture *texture;
|
||||
graphene_rect_t rounded_viewport;
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
GskProfiler *profiler;
|
||||
gint64 cpu_time;
|
||||
@ -244,11 +279,15 @@ gsk_vulkan_renderer_render_texture (GskRenderer *renderer,
|
||||
|
||||
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_framebuffer (self->vulkan,
|
||||
ceil (viewport->size.width),
|
||||
ceil (viewport->size.height));
|
||||
rounded_viewport.size.width,
|
||||
rounded_viewport.size.height);
|
||||
|
||||
gsk_vulkan_render_reset (render, image, viewport, NULL);
|
||||
gsk_vulkan_render_reset (render, image, &rounded_viewport, NULL);
|
||||
gsk_vulkan_render_add_node (render, root);
|
||||
gsk_vulkan_render_upload (render);
|
||||
gsk_vulkan_render_draw (render);
|
||||
@ -301,7 +340,7 @@ gsk_vulkan_renderer_render (GskRenderer *renderer,
|
||||
#endif
|
||||
|
||||
gdk_draw_context_begin_frame (GDK_DRAW_CONTEXT (self->vulkan), region);
|
||||
render = self->render;
|
||||
render = gsk_vulkan_renderer_get_render (self);
|
||||
|
||||
render_region = get_render_region (self);
|
||||
draw_index = gdk_vulkan_context_get_draw_index (self->vulkan);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,10 +12,8 @@ G_BEGIN_DECLS
|
||||
|
||||
GskVulkanRenderPass * gsk_vulkan_render_pass_new (GdkVulkanContext *context,
|
||||
GskVulkanImage *target,
|
||||
float scale_x,
|
||||
float scale_y,
|
||||
graphene_matrix_t *mv,
|
||||
graphene_rect_t *viewport,
|
||||
const graphene_vec2_t *scale,
|
||||
const graphene_rect_t *viewport,
|
||||
cairo_region_t *clip,
|
||||
VkSemaphore signal_semaphore);
|
||||
|
||||
@ -32,8 +30,7 @@ void gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulk
|
||||
GskVulkanRender *render);
|
||||
void gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
|
||||
GskVulkanRender *render,
|
||||
guint layout_count,
|
||||
VkPipelineLayout *pipeline_layout,
|
||||
VkPipelineLayout pipeline_layout,
|
||||
VkCommandBuffer command_buffer);
|
||||
gsize gsk_vulkan_render_pass_get_wait_semaphores (GskVulkanRenderPass *self,
|
||||
VkSemaphore **semaphores);
|
||||
|
@ -51,6 +51,12 @@ typedef enum {
|
||||
GSK_VULKAN_N_PIPELINES
|
||||
} GskVulkanPipelineType;
|
||||
|
||||
typedef enum {
|
||||
GSK_VULKAN_SAMPLER_DEFAULT,
|
||||
GSK_VULKAN_SAMPLER_REPEAT,
|
||||
GSK_VULKAN_SAMPLER_NEAREST
|
||||
} GskVulkanRenderSampler;
|
||||
|
||||
GskVulkanRender * gsk_vulkan_render_new (GskRenderer *renderer,
|
||||
GdkVulkanContext *context);
|
||||
void gsk_vulkan_render_free (GskVulkanRender *self);
|
||||
@ -76,11 +82,12 @@ void gsk_vulkan_render_upload (GskVulk
|
||||
|
||||
GskVulkanPipeline * gsk_vulkan_render_get_pipeline (GskVulkanRender *self,
|
||||
GskVulkanPipelineType pipeline_type);
|
||||
VkDescriptorSet gsk_vulkan_render_get_descriptor_set (GskVulkanRender *self,
|
||||
gsize id);
|
||||
gsize gsk_vulkan_render_reserve_descriptor_set (GskVulkanRender *self,
|
||||
GskVulkanImage *source,
|
||||
gboolean repeat);
|
||||
gsize gsk_vulkan_render_get_sampler_descriptor (GskVulkanRender *self,
|
||||
GskVulkanRenderSampler render_sampler);
|
||||
gsize gsk_vulkan_render_get_image_descriptor (GskVulkanRender *self,
|
||||
GskVulkanImage *source);
|
||||
VkDescriptorSet gsk_vulkan_render_get_descriptor_set (GskVulkanRender *self);
|
||||
|
||||
void gsk_vulkan_render_draw (GskVulkanRender *self);
|
||||
|
||||
void gsk_vulkan_render_submit (GskVulkanRender *self);
|
||||
@ -88,6 +95,7 @@ void gsk_vulkan_render_submit (GskVulk
|
||||
GdkTexture * gsk_vulkan_render_download_target (GskVulkanRender *self);
|
||||
VkFramebuffer gsk_vulkan_render_get_framebuffer (GskVulkanRender *self,
|
||||
GskVulkanImage *image);
|
||||
VkFence gsk_vulkan_render_get_fence (GskVulkanRender *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -14,6 +14,7 @@ struct _GskVulkanTextInstance
|
||||
float rect[4];
|
||||
float tex_rect[4];
|
||||
float color[4];
|
||||
guint32 tex_id[2];
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskVulkanTextPipeline, gsk_vulkan_text_pipeline, GSK_TYPE_VULKAN_PIPELINE)
|
||||
@ -46,6 +47,12 @@ gsk_vulkan_text_pipeline_get_input_state_create_info (GskVulkanPipeline *self)
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanTextInstance, color),
|
||||
},
|
||||
{
|
||||
.location = 3,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_UINT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanTextInstance, tex_id),
|
||||
}
|
||||
};
|
||||
static const VkPipelineVertexInputStateCreateInfo info = {
|
||||
@ -91,18 +98,12 @@ gsk_vulkan_text_pipeline_new (GdkVulkanContext *context,
|
||||
return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_TEXT_PIPELINE, context, layout, shader_name, render_pass);
|
||||
}
|
||||
|
||||
gsize
|
||||
gsk_vulkan_text_pipeline_count_vertex_data (GskVulkanTextPipeline *pipeline,
|
||||
int num_instances)
|
||||
{
|
||||
return sizeof (GskVulkanTextInstance) * num_instances;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline *pipeline,
|
||||
guchar *data,
|
||||
GskVulkanRenderer *renderer,
|
||||
const graphene_rect_t *rect,
|
||||
guint tex_id[2],
|
||||
PangoFont *font,
|
||||
guint total_glyphs,
|
||||
const PangoGlyphInfo *glyphs,
|
||||
@ -153,6 +154,9 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline *pipeline,
|
||||
instance->color[2] = color->blue;
|
||||
instance->color[3] = color->alpha;
|
||||
|
||||
instance->tex_id[0] = tex_id[0];
|
||||
instance->tex_id[1] = tex_id[1];
|
||||
|
||||
count++;
|
||||
}
|
||||
x_position += gi->geometry.width;
|
||||
|
@ -18,24 +18,23 @@ GskVulkanPipeline * gsk_vulkan_text_pipeline_new (GdkVulka
|
||||
const char *shader_name,
|
||||
VkRenderPass render_pass);
|
||||
|
||||
gsize gsk_vulkan_text_pipeline_count_vertex_data (GskVulkanTextPipeline *pipeline,
|
||||
int num_instances);
|
||||
void gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline *pipeline,
|
||||
guchar *data,
|
||||
GskVulkanRenderer *renderer,
|
||||
const graphene_rect_t *rect,
|
||||
PangoFont *font,
|
||||
guint total_glyphs,
|
||||
const PangoGlyphInfo *glyphs,
|
||||
const GdkRGBA *color,
|
||||
const graphene_point_t *offset,
|
||||
guint start_glyph,
|
||||
guint num_glyphs,
|
||||
float scale);
|
||||
guchar *data,
|
||||
GskVulkanRenderer *renderer,
|
||||
const graphene_rect_t *rect,
|
||||
guint32 tex_id[2],
|
||||
PangoFont *font,
|
||||
guint total_glyphs,
|
||||
const PangoGlyphInfo *glyphs,
|
||||
const GdkRGBA *color,
|
||||
const graphene_point_t *offset,
|
||||
guint start_glyph,
|
||||
guint num_glyphs,
|
||||
float scale);
|
||||
gsize gsk_vulkan_text_pipeline_draw (GskVulkanTextPipeline *pipeline,
|
||||
VkCommandBuffer command_buffer,
|
||||
gsize offset,
|
||||
gsize n_commands);
|
||||
VkCommandBuffer command_buffer,
|
||||
gsize offset,
|
||||
gsize n_commands);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -13,6 +13,7 @@ struct _GskVulkanTextureInstance
|
||||
{
|
||||
float rect[4];
|
||||
float tex_rect[4];
|
||||
guint32 tex_id[2];
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskVulkanTexturePipeline, gsk_vulkan_texture_pipeline, GSK_TYPE_VULKAN_PIPELINE)
|
||||
@ -39,6 +40,12 @@ gsk_vulkan_texture_pipeline_get_input_state_create_info (GskVulkanPipeline *self
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanTextureInstance, tex_rect),
|
||||
},
|
||||
{
|
||||
.location = 2,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_UINT,
|
||||
.offset = G_STRUCT_OFFSET (GskVulkanTextureInstance, tex_id),
|
||||
}
|
||||
};
|
||||
static const VkPipelineVertexInputStateCreateInfo info = {
|
||||
@ -84,28 +91,26 @@ gsk_vulkan_texture_pipeline_new (GdkVulkanContext *context,
|
||||
return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_TEXTURE_PIPELINE, context, layout, shader_name, render_pass);
|
||||
}
|
||||
|
||||
gsize
|
||||
gsk_vulkan_texture_pipeline_count_vertex_data (GskVulkanTexturePipeline *pipeline)
|
||||
{
|
||||
return sizeof (GskVulkanTextureInstance);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_texture_pipeline_collect_vertex_data (GskVulkanTexturePipeline *pipeline,
|
||||
guchar *data,
|
||||
guint32 tex_id[2],
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_rect_t *tex_rect)
|
||||
{
|
||||
GskVulkanTextureInstance *instance = (GskVulkanTextureInstance *) data;
|
||||
|
||||
instance->rect[0] = rect->origin.x;
|
||||
instance->rect[1] = rect->origin.y;
|
||||
instance->rect[0] = rect->origin.x + offset->x;
|
||||
instance->rect[1] = rect->origin.y + offset->y;
|
||||
instance->rect[2] = rect->size.width;
|
||||
instance->rect[3] = rect->size.height;
|
||||
instance->tex_rect[0] = tex_rect->origin.x;
|
||||
instance->tex_rect[1] = tex_rect->origin.y;
|
||||
instance->tex_rect[2] = tex_rect->size.width;
|
||||
instance->tex_rect[3] = tex_rect->size.height;
|
||||
instance->tex_id[0] = tex_id[0];
|
||||
instance->tex_id[1] = tex_id[1];
|
||||
}
|
||||
|
||||
gsize
|
||||
|
@ -17,9 +17,10 @@ GskVulkanPipeline * gsk_vulkan_texture_pipeline_new (GdkVulk
|
||||
const char *shader_name,
|
||||
VkRenderPass render_pass);
|
||||
|
||||
gsize gsk_vulkan_texture_pipeline_count_vertex_data (GskVulkanTexturePipeline *pipeline);
|
||||
void gsk_vulkan_texture_pipeline_collect_vertex_data (GskVulkanTexturePipeline *pipeline,
|
||||
guchar *data,
|
||||
guint32 tex_id[2],
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_rect_t *tex_rect);
|
||||
gsize gsk_vulkan_texture_pipeline_draw (GskVulkanTexturePipeline *pipeline,
|
||||
|
@ -1,16 +1,19 @@
|
||||
#version 420 core
|
||||
|
||||
#include "common.frag.glsl"
|
||||
#include "clip.frag.glsl"
|
||||
#include "rect.frag.glsl"
|
||||
|
||||
layout(location = 0) in vec2 inPos;
|
||||
layout(location = 1) in vec2 inStartTexCoord;
|
||||
layout(location = 2) in vec2 inEndTexCoord;
|
||||
layout(location = 3) flat in uint inBlendMode;
|
||||
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 uvec2 inTopTexId;
|
||||
layout(location = 6) flat in uvec2 inBottomTexId;
|
||||
layout(location = 7) flat in uint inBlendMode;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D startTexture;
|
||||
layout(set = 1, binding = 0) uniform sampler2D endTexture;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
float
|
||||
combine (float source, float backdrop)
|
||||
@ -242,7 +245,7 @@ set_sat (vec3 c, float s)
|
||||
}
|
||||
|
||||
vec4
|
||||
color (vec4 Cs, vec4 Cb)
|
||||
colorize (vec4 Cs, vec4 Cb)
|
||||
{
|
||||
vec3 B = set_lum (Cs.rgb, lum (Cb.rgb));
|
||||
return composite (Cs, Cb, B);
|
||||
@ -271,8 +274,10 @@ luminosity (vec4 Cs, vec4 Cb)
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 source = texture (startTexture, inStartTexCoord);
|
||||
vec4 backdrop = texture (endTexture, inEndTexCoord);
|
||||
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)
|
||||
@ -300,7 +305,7 @@ void main()
|
||||
else if (inBlendMode == 11)
|
||||
result = exclusion (source, backdrop);
|
||||
else if (inBlendMode == 12)
|
||||
result = color (source, backdrop);
|
||||
result = colorize (source, backdrop);
|
||||
else if (inBlendMode == 13)
|
||||
result = hue (source, backdrop);
|
||||
else if (inBlendMode == 14)
|
||||
@ -310,5 +315,5 @@ void main()
|
||||
else
|
||||
discard;
|
||||
|
||||
outColor = clip (inPos, result);
|
||||
color = clip_scaled (inPos, result);
|
||||
}
|
||||
|
@ -1,40 +1,36 @@
|
||||
#version 420 core
|
||||
|
||||
#include "clip.vert.glsl"
|
||||
#include "common.vert.glsl"
|
||||
#include "rect.vert.glsl"
|
||||
|
||||
layout(location = 0) in vec4 inRect;
|
||||
layout(location = 1) in vec4 inStartTexRect;
|
||||
layout(location = 2) in vec4 inEndTexRect;
|
||||
layout(location = 3) in uint inBlendMode;
|
||||
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 uvec2 inTopTexId;
|
||||
layout(location = 6) in uvec2 inBottomTexId;
|
||||
layout(location = 7) in uint inBlendMode;
|
||||
|
||||
layout(location = 0) out vec2 outPos;
|
||||
layout(location = 1) out vec2 outStartTexCoord;
|
||||
layout(location = 2) out vec2 outEndTexCoord;
|
||||
layout(location = 3) flat out uint outBlendMode;
|
||||
|
||||
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) };
|
||||
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 uvec2 outTopTexId;
|
||||
layout(location = 6) flat out uvec2 outBottomTexId;
|
||||
layout(location = 7) flat out uint outBlendMode;
|
||||
|
||||
void main() {
|
||||
vec4 rect = clip (inRect);
|
||||
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
|
||||
gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
|
||||
Rect r = rect_from_gsk (inRect);
|
||||
vec2 pos = set_position_from_rect (r);
|
||||
|
||||
outPos = pos;
|
||||
|
||||
vec4 texrect = vec4((rect.xy - inRect.xy) / inRect.zw,
|
||||
rect.zw / inRect.zw);
|
||||
vec4 starttexrect = vec4(inStartTexRect.xy + inStartTexRect.zw * texrect.xy,
|
||||
inStartTexRect.zw * texrect.zw);
|
||||
vec4 endtexrect = vec4(inEndTexRect.xy + inEndTexRect.zw * texrect.xy,
|
||||
inEndTexRect.zw * texrect.zw);
|
||||
|
||||
outStartTexCoord = starttexrect.xy + starttexrect.zw * offsets[gl_VertexIndex];
|
||||
outEndTexCoord = endtexrect.xy + endtexrect.zw * offsets[gl_VertexIndex];
|
||||
|
||||
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,13 +1,13 @@
|
||||
#version 420 core
|
||||
|
||||
#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(set = 0, binding = 0) uniform sampler2D inTexture;
|
||||
layout(location = 4) in flat uvec2 inTexId;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
@ -38,7 +38,7 @@ vec4 blur_pixel (in vec2 uv)
|
||||
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(inTexture, uv + vec2(offset_x, offset_y)) * fx * fy;
|
||||
ret += texture(get_sampler (inTexId), uv + vec2(offset_x, offset_y)) * fx * fy;
|
||||
}
|
||||
}
|
||||
return ret / total;
|
||||
|
@ -6,11 +6,13 @@
|
||||
layout(location = 0) in vec4 inRect;
|
||||
layout(location = 1) in vec4 inTexRect;
|
||||
layout(location = 2) in float inRadius;
|
||||
layout(location = 3) in uvec2 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 uvec2 outTexId;
|
||||
|
||||
vec2 offsets[6] = { vec2(0.0, 0.0),
|
||||
vec2(1.0, 0.0),
|
||||
@ -22,7 +24,7 @@ vec2 offsets[6] = { vec2(0.0, 0.0),
|
||||
void main() {
|
||||
vec4 rect = clip (inRect);
|
||||
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
|
||||
gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
|
||||
gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
|
||||
|
||||
outPos = pos;
|
||||
outSize = inRect.zw;
|
||||
@ -32,6 +34,6 @@ void main() {
|
||||
texrect = vec4(inTexRect.xy + inTexRect.zw * texrect.xy,
|
||||
inTexRect.zw * texrect.zw);
|
||||
outTexCoord = texrect.xy + texrect.zw * offsets[gl_VertexIndex];
|
||||
|
||||
outTexId = inTexId;
|
||||
outRadius = inRadius;
|
||||
}
|
||||
|
@ -5,20 +5,18 @@
|
||||
|
||||
layout(location = 0) in vec2 inPos;
|
||||
layout(location = 1) in vec4 inColor;
|
||||
layout(location = 2) in vec4 inRect;
|
||||
layout(location = 3) in vec4 inCornerWidths;
|
||||
layout(location = 4) in vec4 inCornerHeights;
|
||||
layout(location = 2) in RoundedRect inRect;
|
||||
layout(location = 5) in vec4 inBorderWidths;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
RoundedRect routside = RoundedRect (vec4(inRect.xy, inRect.xy + inRect.zw), inCornerWidths, inCornerHeights);
|
||||
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 (inPos, vec4(inColor.rgb * inColor.a, inColor.a) * alpha);
|
||||
color = clip_scaled (inPos, vec4(inColor.rgb * inColor.a, inColor.a) * alpha);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#version 420 core
|
||||
|
||||
#include "clip.vert.glsl"
|
||||
#include "rounded-rect.glsl"
|
||||
|
||||
layout(location = 0) in vec4 inRect;
|
||||
layout(location = 1) in vec4 inCornerWidths;
|
||||
@ -10,9 +11,7 @@ layout(location = 4) in mat4 inBorderColors;
|
||||
|
||||
layout(location = 0) out vec2 outPos;
|
||||
layout(location = 1) out flat vec4 outColor;
|
||||
layout(location = 2) out flat vec4 outRect;
|
||||
layout(location = 3) out flat vec4 outCornerWidths;
|
||||
layout(location = 4) out flat vec4 outCornerHeights;
|
||||
layout(location = 2) out flat RoundedRect outRect;
|
||||
layout(location = 5) out flat vec4 outBorderWidths;
|
||||
|
||||
vec2 offsets[6] = { vec2(0.0, 0.0),
|
||||
@ -48,51 +47,59 @@ void main() {
|
||||
vec4 corner_widths = max (inCornerWidths, inBorderWidths.wyyw);
|
||||
vec4 corner_heights = max (inCornerHeights, inBorderWidths.xxzz);
|
||||
|
||||
vec4 rect;
|
||||
Rect rect;
|
||||
|
||||
switch (slice_index)
|
||||
{
|
||||
case SLICE_TOP_LEFT:
|
||||
rect = vec4(inRect.xy, corner_widths[TOP_LEFT], corner_heights[TOP_LEFT]);
|
||||
rect = rect_from_gsk (vec4(inRect.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 = vec4(inRect.x + corner_widths[TOP_LEFT], inRect.y, inRect.z - corner_widths[TOP_LEFT] - corner_widths[TOP_RIGHT], inBorderWidths[TOP]);
|
||||
rect = rect_from_gsk (vec4(inRect.x + corner_widths[TOP_LEFT], inRect.y, inRect.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 = vec4(inRect.x + inRect.z - corner_widths[TOP_RIGHT], inRect.y, corner_widths[TOP_RIGHT], corner_heights[TOP_RIGHT]);
|
||||
rect = rect_from_gsk (vec4(inRect.x + inRect.z - corner_widths[TOP_RIGHT], inRect.y, corner_widths[TOP_RIGHT], corner_heights[TOP_RIGHT]));
|
||||
rect = rect_round_larger (rect);
|
||||
break;
|
||||
case SLICE_RIGHT:
|
||||
rect = vec4(inRect.x + inRect.z - inBorderWidths[RIGHT], inRect.y + corner_heights[TOP_RIGHT], inBorderWidths[RIGHT], inRect.w - corner_heights[TOP_RIGHT] - corner_heights[BOTTOM_RIGHT]);
|
||||
rect = rect_from_gsk (vec4(inRect.x + inRect.z - inBorderWidths[RIGHT], inRect.y + corner_heights[TOP_RIGHT], inBorderWidths[RIGHT], inRect.w - corner_heights[TOP_RIGHT] - corner_heights[BOTTOM_RIGHT]));
|
||||
rect = rect_round_larger_smaller (rect);
|
||||
outColor = inBorderColors[RIGHT];
|
||||
break;
|
||||
case SLICE_BOTTOM_RIGHT:
|
||||
rect = vec4(inRect.x + inRect.z - corner_widths[BOTTOM_RIGHT], inRect.y + inRect.w - corner_heights[BOTTOM_RIGHT], corner_widths[BOTTOM_RIGHT], corner_heights[BOTTOM_RIGHT]);
|
||||
rect = rect_from_gsk (vec4(inRect.x + inRect.z - corner_widths[BOTTOM_RIGHT], inRect.y + inRect.w - corner_heights[BOTTOM_RIGHT], corner_widths[BOTTOM_RIGHT], corner_heights[BOTTOM_RIGHT]));
|
||||
rect = rect_round_larger (rect);
|
||||
break;
|
||||
case SLICE_BOTTOM:
|
||||
rect = vec4(inRect.x + corner_widths[BOTTOM_LEFT], inRect.y + inRect.w - inBorderWidths[BOTTOM], inRect.z - corner_widths[BOTTOM_LEFT] - corner_widths[BOTTOM_RIGHT], inBorderWidths[BOTTOM]);
|
||||
rect = rect_from_gsk (vec4(inRect.x + corner_widths[BOTTOM_LEFT], inRect.y + inRect.w - inBorderWidths[BOTTOM], inRect.z - corner_widths[BOTTOM_LEFT] - corner_widths[BOTTOM_RIGHT], inBorderWidths[BOTTOM]));
|
||||
rect = rect_round_smaller_larger (rect);
|
||||
break;
|
||||
case SLICE_BOTTOM_LEFT:
|
||||
rect = vec4(inRect.x, inRect.y + inRect.w - corner_heights[BOTTOM_LEFT], corner_widths[BOTTOM_LEFT], corner_heights[BOTTOM_LEFT]);
|
||||
rect = rect_from_gsk (vec4(inRect.x, inRect.y + inRect.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 = vec4(inRect.x, inRect.y + corner_heights[TOP_LEFT], inBorderWidths[LEFT], inRect.w - corner_heights[TOP_LEFT] - corner_heights[BOTTOM_LEFT]);
|
||||
rect = rect_from_gsk (vec4(inRect.x, inRect.y + corner_heights[TOP_LEFT], inBorderWidths[LEFT], inRect.w - corner_heights[TOP_LEFT] - corner_heights[BOTTOM_LEFT]));
|
||||
rect = rect_round_larger_smaller (rect);
|
||||
break;
|
||||
}
|
||||
|
||||
rect = clip (rect);
|
||||
rect = clip_rect (rect);
|
||||
|
||||
vec2 pos;
|
||||
if ((slice_index % 4) != 0 || (vert_index % 3) != 2)
|
||||
pos = rect.xy + rect.zw * offsets[vert_index];
|
||||
pos = mix (rect.bounds.xy, rect.bounds.zw, offsets[vert_index]);
|
||||
else
|
||||
pos = rect.xy + rect.zw * vec2(1.0 - offsets[vert_index].x, offsets[vert_index].y);
|
||||
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 = inRect;
|
||||
outCornerWidths = inCornerWidths;
|
||||
outCornerHeights = inCornerHeights;
|
||||
outBorderWidths = inBorderWidths;
|
||||
outRect = RoundedRect(inRect.xyxy + vec4(0,0,inRect.zw), inCornerWidths, inCornerHeights);
|
||||
outRect = rounded_rect_scale (outRect, push.scale);
|
||||
outBorderWidths = inBorderWidths * push.scale.yxyx;
|
||||
}
|
||||
|
@ -1,29 +1,45 @@
|
||||
#include "constants.glsl"
|
||||
#include "rounded-rect.glsl"
|
||||
#include "rounded-rect.frag.glsl"
|
||||
|
||||
#ifndef _CLIP_
|
||||
#define _CLIP_
|
||||
|
||||
#ifdef CLIP_ROUNDED_RECT
|
||||
vec4 clip(vec2 pos, vec4 color)
|
||||
|
||||
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(vec2 pos, vec4 color)
|
||||
|
||||
vec4
|
||||
clip_scaled (vec2 pos, vec4 color)
|
||||
{
|
||||
/* clipped in vertex shader already */
|
||||
return color;
|
||||
}
|
||||
|
||||
#elif defined(CLIP_NONE)
|
||||
vec4 clip(vec2 pos, vec4 color)
|
||||
|
||||
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,4 +1,5 @@
|
||||
#include "constants.glsl"
|
||||
#include "rect.vert.glsl"
|
||||
|
||||
#ifndef _CLIP_
|
||||
#define _CLIP_
|
||||
@ -14,21 +15,47 @@ vec4 intersect(vec4 a, vec4 b)
|
||||
}
|
||||
|
||||
#ifdef CLIP_ROUNDED_RECT
|
||||
vec4 clip(vec4 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)
|
||||
|
||||
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
|
||||
|
@ -1,13 +1,13 @@
|
||||
#version 420 core
|
||||
|
||||
#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(set = 0, binding = 0) uniform sampler2D inTexture;
|
||||
layout(location = 7) in flat uvec2 inTexId;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
@ -29,5 +29,5 @@ color_matrix (vec4 color, mat4 color_matrix, vec4 color_offset)
|
||||
|
||||
void main()
|
||||
{
|
||||
color = clip (inPos, color_matrix (texture (inTexture, inTexCoord), inColorMatrix, inColorOffset));
|
||||
color = clip (inPos, color_matrix (texture (get_sampler (inTexId), inTexCoord), inColorMatrix, inColorOffset));
|
||||
}
|
||||
|
@ -6,11 +6,13 @@ 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 uvec2 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 uvec2 outTexId;
|
||||
|
||||
vec2 offsets[6] = { vec2(0.0, 0.0),
|
||||
vec2(1.0, 0.0),
|
||||
@ -22,7 +24,7 @@ vec2 offsets[6] = { vec2(0.0, 0.0),
|
||||
void main() {
|
||||
vec4 rect = clip (inRect);
|
||||
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
|
||||
gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
|
||||
gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
|
||||
|
||||
outPos = pos;
|
||||
|
||||
@ -31,6 +33,7 @@ void main() {
|
||||
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,13 +1,16 @@
|
||||
#version 420 core
|
||||
|
||||
#include "clip.frag.glsl"
|
||||
#include "rect.frag.glsl"
|
||||
|
||||
layout(location = 0) in vec2 inPos;
|
||||
layout(location = 1) in vec4 inColor;
|
||||
layout(location = 1) in Rect inRect;
|
||||
layout(location = 2) in vec4 inColor;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = clip (inPos, vec4(inColor.rgb * inColor.a, inColor.a));
|
||||
float alpha = inColor.a * rect_coverage (inRect, inPos);
|
||||
color = clip_scaled (inPos, vec4(inColor.rgb, 1) * alpha);
|
||||
}
|
||||
|
@ -1,25 +1,18 @@
|
||||
#version 420 core
|
||||
|
||||
#include "clip.vert.glsl"
|
||||
#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 vec4 outColor;
|
||||
|
||||
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) };
|
||||
layout(location = 1) out flat Rect outRect;
|
||||
layout(location = 2) out flat vec4 outColor;
|
||||
|
||||
void main() {
|
||||
vec4 rect = clip (inRect);
|
||||
|
||||
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
|
||||
gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
|
||||
outPos = pos;
|
||||
Rect r = rect_from_gsk (inRect);
|
||||
outPos = set_position_from_rect (r);
|
||||
outRect = r;
|
||||
outColor = inColor;
|
||||
}
|
||||
|
6
gsk/vulkan/resources/common.frag.glsl
Normal file
6
gsk/vulkan/resources/common.frag.glsl
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
layout(set = 0, binding = 0) uniform texture2D textures[50000];
|
||||
layout(set = 0, binding = 1) uniform sampler samplers[50000];
|
||||
|
||||
#define get_sampler(id) sampler2D(textures[id.x], samplers[id.y])
|
||||
|
34
gsk/vulkan/resources/common.vert.glsl
Normal file
34
gsk/vulkan/resources/common.vert.glsl
Normal file
@ -0,0 +1,34 @@
|
||||
#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
|
@ -6,6 +6,7 @@ layout(push_constant) uniform PushConstants {
|
||||
vec4 clip_bounds;
|
||||
vec4 clip_widths;
|
||||
vec4 clip_heights;
|
||||
vec2 scale;
|
||||
} push;
|
||||
|
||||
#endif
|
||||
|
@ -1,21 +1,26 @@
|
||||
#version 420 core
|
||||
|
||||
#include "common.frag.glsl"
|
||||
#include "clip.frag.glsl"
|
||||
#include "rect.frag.glsl"
|
||||
|
||||
layout(location = 0) in vec2 inPos;
|
||||
layout(location = 1) in vec2 inStartTexCoord;
|
||||
layout(location = 2) in vec2 inEndTexCoord;
|
||||
layout(location = 3) in float inProgress;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D startTexture;
|
||||
layout(set = 1, binding = 0) uniform sampler2D endTexture;
|
||||
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 uvec2 inStartTexId;
|
||||
layout(location = 6) flat in uvec2 inEndTexId;
|
||||
layout(location = 7) in float inProgress;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 start = texture (startTexture, inStartTexCoord);
|
||||
vec4 end = texture (endTexture, inEndTexCoord);
|
||||
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 (inPos, mix (start, end, inProgress));
|
||||
color = clip_scaled (inPos, mix (start, end, inProgress));
|
||||
}
|
||||
|
@ -1,40 +1,36 @@
|
||||
#version 420 core
|
||||
|
||||
#include "clip.vert.glsl"
|
||||
#include "common.vert.glsl"
|
||||
#include "rect.vert.glsl"
|
||||
|
||||
layout(location = 0) in vec4 inRect;
|
||||
layout(location = 1) in vec4 inStartTexRect;
|
||||
layout(location = 2) in vec4 inEndTexRect;
|
||||
layout(location = 3) in float inProgress;
|
||||
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 uvec2 inStartTexId;
|
||||
layout(location = 6) in uvec2 inEndTexId;
|
||||
layout(location = 7) in float inProgress;
|
||||
|
||||
layout(location = 0) out vec2 outPos;
|
||||
layout(location = 1) out vec2 outStartTexCoord;
|
||||
layout(location = 2) out vec2 outEndTexCoord;
|
||||
layout(location = 3) out float outProgress;
|
||||
|
||||
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) };
|
||||
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 uvec2 outStartTexId;
|
||||
layout(location = 6) flat out uvec2 outEndTexId;
|
||||
layout(location = 7) flat out float outProgress;
|
||||
|
||||
void main() {
|
||||
vec4 rect = clip (inRect);
|
||||
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
|
||||
gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
|
||||
Rect r = rect_from_gsk (inRect);
|
||||
vec2 pos = set_position_from_rect (r);
|
||||
|
||||
outPos = pos;
|
||||
|
||||
vec4 texrect = vec4((rect.xy - inRect.xy) / inRect.zw,
|
||||
rect.zw / inRect.zw);
|
||||
vec4 starttexrect = vec4(inStartTexRect.xy + inStartTexRect.zw * texrect.xy,
|
||||
inStartTexRect.zw * texrect.zw);
|
||||
vec4 endtexrect = vec4(inEndTexRect.xy + inEndTexRect.zw * texrect.xy,
|
||||
inEndTexRect.zw * texrect.zw);
|
||||
|
||||
outStartTexCoord = starttexrect.xy + starttexrect.zw * offsets[gl_VertexIndex];
|
||||
outEndTexCoord = endtexrect.xy + endtexrect.zw * offsets[gl_VertexIndex];
|
||||
|
||||
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;
|
||||
}
|
||||
|
38
gsk/vulkan/resources/ellipse.glsl
Normal file
38
gsk/vulkan/resources/ellipse.glsl
Normal file
@ -0,0 +1,38 @@
|
||||
#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
|
@ -29,7 +29,7 @@ void main() {
|
||||
vec4 rect = clip (inOutline);
|
||||
|
||||
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
|
||||
gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
|
||||
gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
|
||||
outPos = pos;
|
||||
|
||||
outOutline = inOutline;
|
||||
|
@ -48,7 +48,7 @@ get_gradient_pos (vec2 pos)
|
||||
void main() {
|
||||
vec4 rect = clip (inRect);
|
||||
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
|
||||
gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
|
||||
gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
|
||||
outPos = pos;
|
||||
outGradientPos = get_gradient_pos (pos);
|
||||
outRepeating = inRepeating;
|
||||
|
@ -1,16 +1,16 @@
|
||||
#version 420 core
|
||||
|
||||
#include "common.frag.glsl"
|
||||
#include "clip.frag.glsl"
|
||||
|
||||
layout(location = 0) in vec2 inPos;
|
||||
layout(location = 1) in vec2 inTexCoord;
|
||||
layout(location = 2) in vec4 inColor;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D inTexture;
|
||||
layout(location = 3) flat in uvec2 inTexId;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = clip (inPos, vec4(inColor.rgb * inColor.a, inColor.a) * texture(inTexture, inTexCoord).a);
|
||||
color = clip (inPos, vec4(inColor.rgb * inColor.a, inColor.a) * texture(get_sampler (inTexId), inTexCoord).a);
|
||||
}
|
||||
|
@ -5,10 +5,12 @@
|
||||
layout(location = 0) in vec4 inRect;
|
||||
layout(location = 1) in vec4 inTexRect;
|
||||
layout(location = 2) in vec4 inColor;
|
||||
layout(location = 3) in uvec2 inTexId;
|
||||
|
||||
layout(location = 0) out vec2 outPos;
|
||||
layout(location = 1) out vec2 outTexCoord;
|
||||
layout(location = 2) out flat vec4 outColor;
|
||||
layout(location = 3) out flat uvec2 outTexId;
|
||||
|
||||
vec2 offsets[6] = { vec2(0.0, 0.0),
|
||||
vec2(1.0, 0.0),
|
||||
@ -20,7 +22,7 @@ vec2 offsets[6] = { vec2(0.0, 0.0),
|
||||
void main() {
|
||||
vec4 rect = clip (inRect);
|
||||
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
|
||||
gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
|
||||
gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
|
||||
|
||||
outPos = pos;
|
||||
|
||||
@ -29,6 +31,6 @@ void main() {
|
||||
texrect = vec4(inTexRect.xy + inTexRect.zw * texrect.xy,
|
||||
inTexRect.zw * texrect.zw);
|
||||
outTexCoord = texrect.xy + texrect.zw * offsets[gl_VertexIndex];
|
||||
|
||||
outTexId = inTexId;
|
||||
outColor = inColor;
|
||||
}
|
||||
|
@ -1,8 +1,14 @@
|
||||
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 = [
|
||||
|
@ -38,7 +38,7 @@ void main() {
|
||||
clip (inOutline);
|
||||
|
||||
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
|
||||
gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
|
||||
gl_Position = push.mvp * vec4 (push.scale * pos, 0.0, 1.0);
|
||||
outPos = pos;
|
||||
|
||||
outOutline = inOutline;
|
||||
|
16
gsk/vulkan/resources/rect.frag.glsl
Normal file
16
gsk/vulkan/resources/rect.frag.glsl
Normal file
@ -0,0 +1,16 @@
|
||||
#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
|
58
gsk/vulkan/resources/rect.glsl
Normal file
58
gsk/vulkan/resources/rect.glsl
Normal file
@ -0,0 +1,58 @@
|
||||
#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);
|
||||
}
|
||||
|
||||
#endif
|
6
gsk/vulkan/resources/rect.vert.glsl
Normal file
6
gsk/vulkan/resources/rect.vert.glsl
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef _RECT_VERT_
|
||||
#define _RECT_VERT_
|
||||
|
||||
#include "rect.glsl"
|
||||
|
||||
#endif
|
17
gsk/vulkan/resources/rounded-rect.frag.glsl
Normal file
17
gsk/vulkan/resources/rounded-rect.frag.glsl
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef _ROUNDED_RECT_FRAG_
|
||||
#define _ROUNDED_RECT_FRAG_
|
||||
|
||||
#include "rounded-rect.glsl"
|
||||
|
||||
float
|
||||
rounded_rect_coverage (RoundedRect r, vec2 p)
|
||||
{
|
||||
vec2 fw = abs (fwidth (p));
|
||||
float distance_scale = max (fw.x, fw.y);
|
||||
float distance = rounded_rect_distance (r, p) / distance_scale;
|
||||
float coverage = 0.5 - distance;
|
||||
|
||||
return clamp (coverage, 0, 1);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,6 +1,9 @@
|
||||
#ifndef _ROUNDED_RECT_
|
||||
#define _ROUNDED_RECT_
|
||||
|
||||
#include "ellipse.glsl"
|
||||
#include "rect.glsl"
|
||||
|
||||
struct RoundedRect
|
||||
{
|
||||
vec4 bounds;
|
||||
@ -9,59 +12,52 @@ struct RoundedRect
|
||||
};
|
||||
|
||||
float
|
||||
ellipsis_dist (vec2 p, vec2 radius)
|
||||
rounded_rect_distance (RoundedRect r, vec2 p)
|
||||
{
|
||||
vec2 p0 = p / radius;
|
||||
vec2 p1 = 2.0 * p0 / radius;
|
||||
|
||||
return (dot(p0, p0) - 1.0) / length (p1);
|
||||
}
|
||||
Rect bounds = Rect(vec4(r.bounds));
|
||||
|
||||
float
|
||||
ellipsis_coverage (vec2 point, vec2 center, vec2 radius)
|
||||
{
|
||||
float d = ellipsis_dist (point - center, radius);
|
||||
return clamp (0.5 - d, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float
|
||||
rounded_rect_coverage (RoundedRect r, vec2 p)
|
||||
{
|
||||
if (p.x < r.bounds.x || p.y < r.bounds.y ||
|
||||
p.x >= r.bounds.z || p.y >= r.bounds.w)
|
||||
return 0.0;
|
||||
float bounds_distance = rect_distance (bounds, p);
|
||||
|
||||
vec2 rad_tl = vec2(r.corner_widths.x, r.corner_heights.x);
|
||||
vec2 rad_tr = vec2(r.corner_widths.y, r.corner_heights.y);
|
||||
vec2 rad_br = vec2(r.corner_widths.z, r.corner_heights.z);
|
||||
vec2 rad_bl = vec2(r.corner_widths.w, r.corner_heights.w);
|
||||
|
||||
vec2 ref_tl = r.bounds.xy + vec2( r.corner_widths.x, r.corner_heights.x);
|
||||
vec2 ref_tr = r.bounds.zy + vec2(-r.corner_widths.y, r.corner_heights.y);
|
||||
vec2 ref_br = r.bounds.zw + vec2(-r.corner_widths.z, -r.corner_heights.z);
|
||||
vec2 ref_bl = r.bounds.xw + vec2( r.corner_widths.w, -r.corner_heights.w);
|
||||
Ellipse tl = Ellipse (r.bounds.xy + vec2( r.corner_widths.x, r.corner_heights.x),
|
||||
vec2(r.corner_widths.x, r.corner_heights.x));
|
||||
Ellipse tr = Ellipse (r.bounds.zy + vec2(-r.corner_widths.y, r.corner_heights.y),
|
||||
vec2(r.corner_widths.y, r.corner_heights.y));
|
||||
Ellipse br = Ellipse (r.bounds.zw + vec2(-r.corner_widths.z, -r.corner_heights.z),
|
||||
vec2(r.corner_widths.z, r.corner_heights.z));
|
||||
Ellipse bl = Ellipse (r.bounds.xw + vec2( r.corner_widths.w, -r.corner_heights.w),
|
||||
vec2(r.corner_widths.w, r.corner_heights.w));
|
||||
|
||||
float d_tl = ellipsis_coverage(p, ref_tl, rad_tl);
|
||||
float d_tr = ellipsis_coverage(p, ref_tr, rad_tr);
|
||||
float d_br = ellipsis_coverage(p, ref_br, rad_br);
|
||||
float d_bl = ellipsis_coverage(p, ref_bl, rad_bl);
|
||||
vec4 distances = vec4(ellipse_distance (tl, p),
|
||||
ellipse_distance (tr, p),
|
||||
ellipse_distance (br, p),
|
||||
ellipse_distance (bl, p));
|
||||
|
||||
vec4 corner_coverages = 1.0 - vec4(d_tl, d_tr, d_br, d_bl);
|
||||
bvec4 is_out = bvec4(p.x < tl.center.x && p.y < tl.center.y,
|
||||
p.x > tr.center.x && p.y < tr.center.y,
|
||||
p.x > br.center.x && p.y > br.center.y,
|
||||
p.x < bl.center.x && p.y > bl.center.y);
|
||||
distances = mix (vec4(bounds_distance), distances, is_out);
|
||||
|
||||
bvec4 is_out = bvec4(p.x < ref_tl.x && p.y < ref_tl.y,
|
||||
p.x > ref_tr.x && p.y < ref_tr.y,
|
||||
p.x > ref_br.x && p.y > ref_br.y,
|
||||
p.x < ref_bl.x && p.y > ref_bl.y);
|
||||
vec2 max2 = max (distances.xy, distances.zw);
|
||||
return max (max2.x, max2.y);
|
||||
}
|
||||
|
||||
return 1.0 - dot(vec4(is_out), corner_coverages);
|
||||
RoundedRect
|
||||
rounded_rect_scale (RoundedRect r, vec2 scale)
|
||||
{
|
||||
r.bounds *= scale.xyxy;
|
||||
r.corner_widths *= scale.xxxx;
|
||||
r.corner_heights *= scale.yyyy;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
RoundedRect
|
||||
rounded_rect_shrink (RoundedRect r, vec4 amount)
|
||||
{
|
||||
vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz;
|
||||
vec4 new_widths = max (r.corner_widths - amount.wyyw, 0.0);
|
||||
vec4 new_heights = max (r.corner_heights - amount.xxzz, 0.0);
|
||||
vec4 new_widths = max (r.corner_widths - sign (r.corner_widths) * amount.wyyw, 0.0);
|
||||
vec4 new_heights = max (r.corner_heights - sign (r.corner_heights) * amount.xxzz, 0.0);
|
||||
|
||||
return RoundedRect (new_bounds, new_widths, new_heights);
|
||||
}
|
||||
|
@ -1,15 +1,18 @@
|
||||
#version 420 core
|
||||
|
||||
#include "common.frag.glsl"
|
||||
#include "clip.frag.glsl"
|
||||
#include "rect.frag.glsl"
|
||||
|
||||
layout(location = 0) in vec2 inPos;
|
||||
layout(location = 1) in vec2 inTexCoord;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D inTexture;
|
||||
layout(location = 1) in Rect inRect;
|
||||
layout(location = 2) in vec2 inTexCoord;
|
||||
layout(location = 3) flat in uvec2 inTexId;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = clip (inPos, texture (inTexture, inTexCoord));
|
||||
float alpha = rect_coverage (inRect, inPos);
|
||||
color = clip_scaled (inPos, texture (get_sampler (inTexId), inTexCoord) * alpha);
|
||||
}
|
||||
|
@ -1,30 +1,23 @@
|
||||
#version 420 core
|
||||
|
||||
#include "clip.vert.glsl"
|
||||
#include "common.vert.glsl"
|
||||
#include "rect.vert.glsl"
|
||||
|
||||
layout(location = 0) in vec4 inRect;
|
||||
layout(location = 1) in vec4 inTexRect;
|
||||
layout(location = 2) in uvec2 inTexId;
|
||||
|
||||
layout(location = 0) out vec2 outPos;
|
||||
layout(location = 1) out vec2 outTexCoord;
|
||||
|
||||
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) };
|
||||
layout(location = 1) out flat Rect outRect;
|
||||
layout(location = 2) out vec2 outTexCoord;
|
||||
layout(location = 3) out flat uvec2 outTexId;
|
||||
|
||||
void main() {
|
||||
vec4 rect = clip (inRect);
|
||||
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
|
||||
gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
|
||||
Rect r = rect_from_gsk (inRect);
|
||||
vec2 pos = set_position_from_rect (r);
|
||||
|
||||
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];
|
||||
outRect = r;
|
||||
outTexCoord = scale_tex_coord (pos, r, inTexRect);
|
||||
outTexId = inTexId;
|
||||
}
|
||||
|
@ -1267,7 +1267,7 @@ populate_render_node_properties (GListStore *store,
|
||||
float radius = gsk_outset_shadow_node_get_blur_radius (node);
|
||||
float rect[12];
|
||||
|
||||
gsk_rounded_rect_to_float (outline, rect);
|
||||
gsk_rounded_rect_to_float (outline, graphene_point_zero (), rect);
|
||||
tmp = g_strdup_printf ("%.2f x %.2f + %.2f + %.2f",
|
||||
rect[2], rect[3], rect[0], rect[1]);
|
||||
add_text_row (store, "Outline", tmp);
|
||||
|
24
testsuite/gsk/compare/repeat-empty-child-bounds.node
Normal file
24
testsuite/gsk/compare/repeat-empty-child-bounds.node
Normal file
@ -0,0 +1,24 @@
|
||||
repeat {
|
||||
bounds: 0 0 100 100;
|
||||
child-bounds: 0 0 0 0;
|
||||
child: color {
|
||||
bounds: 0 0 20 20;
|
||||
color: rgb(255,0,0);
|
||||
}
|
||||
}
|
||||
repeat {
|
||||
bounds: 0 0 100 100;
|
||||
child-bounds: 0 0 20 0;
|
||||
child: color {
|
||||
bounds: 0 0 20 20;
|
||||
color: rgb(0,128,0);
|
||||
}
|
||||
}
|
||||
repeat {
|
||||
bounds: 0 0 100 100;
|
||||
child-bounds: 0 0 0 20;
|
||||
child: color {
|
||||
bounds: 0 0 20 20;
|
||||
color: rgb(0,0,255);
|
||||
}
|
||||
}
|
BIN
testsuite/gsk/compare/repeat-empty-child-bounds.png
Normal file
BIN
testsuite/gsk/compare/repeat-empty-child-bounds.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 119 B |
@ -77,6 +77,7 @@ compare_render_tests = [
|
||||
'outset_shadow_simple',
|
||||
'repeat',
|
||||
'repeat-no-repeat',
|
||||
'repeat-empty-child-bounds',
|
||||
'repeat-negative-coords',
|
||||
'repeat-texture',
|
||||
'scale-textures-negative-ngl',
|
||||
|
@ -152,12 +152,19 @@ test_to_float (void)
|
||||
&GRAPHENE_SIZE_INIT (8, 9),
|
||||
&GRAPHENE_SIZE_INIT (10, 11));
|
||||
|
||||
gsk_rounded_rect_to_float (&rect, flt);
|
||||
gsk_rounded_rect_to_float (&rect, &GRAPHENE_POINT_INIT(0, 0), flt);
|
||||
g_assert_true (flt[0] == 0. && flt[1] == 11. && flt[2] == 22. && flt[3] == 33.);
|
||||
g_assert_true (flt[4] == 4. && flt[5] == 6.);
|
||||
g_assert_true (flt[6] == 8. && flt[7] == 10.);
|
||||
g_assert_true (flt[8] == 5. && flt[9] == 7.);
|
||||
g_assert_true (flt[10] == 9. && flt[11] == 11.);
|
||||
|
||||
gsk_rounded_rect_to_float (&rect, &GRAPHENE_POINT_INIT(100, 200), flt);
|
||||
g_assert_true (flt[0] == 100. && flt[1] == 211. && flt[2] == 22. && flt[3] == 33.);
|
||||
g_assert_true (flt[4] == 4. && flt[5] == 6.);
|
||||
g_assert_true (flt[6] == 8. && flt[7] == 10.);
|
||||
g_assert_true (flt[8] == 5. && flt[9] == 7.);
|
||||
g_assert_true (flt[10] == 9. && flt[11] == 11.);
|
||||
}
|
||||
|
||||
#define ROUNDED_RECT_INIT_FULL(x,y,w,h,w0,h0,w1,h1,w2,h2,w3,h3) \
|
||||
@ -234,6 +241,145 @@ test_intersect_with_rect (void)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_intersect (void)
|
||||
{
|
||||
struct {
|
||||
GskRoundedRect a;
|
||||
GskRoundedRect b;
|
||||
GskRoundedRectIntersection result;
|
||||
GskRoundedRect expected;
|
||||
} test[] = {
|
||||
{
|
||||
ROUNDED_RECT_INIT(0, 0, 100, 100, 0),
|
||||
ROUNDED_RECT_INIT(0, 0, 100, 100, 20),
|
||||
GSK_INTERSECTION_NONEMPTY,
|
||||
ROUNDED_RECT_INIT(0, 0, 100, 100, 20),
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT(0, 0, 100, 100, 20),
|
||||
ROUNDED_RECT_INIT(50, 50, 100, 100, 20),
|
||||
GSK_INTERSECTION_NONEMPTY,
|
||||
ROUNDED_RECT_INIT_UNIFORM(50, 50, 50, 50, 20, 0, 20, 0),
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT(0, 0, 100, 100, 20),
|
||||
ROUNDED_RECT_INIT(50, 0, 100, 100, 20),
|
||||
GSK_INTERSECTION_NONEMPTY,
|
||||
ROUNDED_RECT_INIT(50, 0, 50, 100, 20),
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT(0, 0, 100, 100, 20),
|
||||
ROUNDED_RECT_INIT(0, 50, 100, 100, 20),
|
||||
GSK_INTERSECTION_NONEMPTY,
|
||||
ROUNDED_RECT_INIT(0, 50, 100, 50, 20),
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT(0, 0, 100, 100, 20),
|
||||
ROUNDED_RECT_INIT(-50, -50, 100, 100, 20),
|
||||
GSK_INTERSECTION_NONEMPTY,
|
||||
ROUNDED_RECT_INIT_UNIFORM(0, 0, 50, 50, 20, 0, 20, 0),
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT(0, 0, 100, 100, 20),
|
||||
ROUNDED_RECT_INIT(0, -50, 100, 100, 20),
|
||||
GSK_INTERSECTION_NONEMPTY,
|
||||
ROUNDED_RECT_INIT(0, 0, 100, 50, 20),
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT(0, 0, 100, 100, 20),
|
||||
ROUNDED_RECT_INIT(-50, 0, 100, 100, 20),
|
||||
GSK_INTERSECTION_NONEMPTY,
|
||||
ROUNDED_RECT_INIT(0, 0, 50, 100, 20),
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT(0, 0, 100, 100, 20),
|
||||
ROUNDED_RECT_INIT(10, 10, 80, 80, 20),
|
||||
GSK_INTERSECTION_NONEMPTY,
|
||||
ROUNDED_RECT_INIT(10, 10, 80, 80, 20),
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT(0, 0, 100, 100, 20),
|
||||
ROUNDED_RECT_INIT(10, 10, 80, 80, 10),
|
||||
GSK_INTERSECTION_NONEMPTY,
|
||||
ROUNDED_RECT_INIT(10, 10, 80, 80, 10),
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT(0, 0, 100, 100, 40),
|
||||
ROUNDED_RECT_INIT(10, 10, 80, 80, 0),
|
||||
GSK_INTERSECTION_NOT_REPRESENTABLE,
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT(10, 10, 100, 100, 40),
|
||||
ROUNDED_RECT_INIT(30, 0, 40, 40, 0),
|
||||
GSK_INTERSECTION_NOT_REPRESENTABLE,
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT(10, 10, 100, 100, 40),
|
||||
ROUNDED_RECT_INIT(0, 0, 100, 20, 0),
|
||||
GSK_INTERSECTION_NOT_REPRESENTABLE,
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT_UNIFORM(647, 18, 133, 35, 5, 0, 0, 5),
|
||||
ROUNDED_RECT_INIT_UNIFORM(14, 12, 1666, 889, 8, 8, 0, 0),
|
||||
GSK_INTERSECTION_NONEMPTY,
|
||||
ROUNDED_RECT_INIT_UNIFORM(647, 18, 133, 35, 5, 0, 0, 5),
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT_UNIFORM(0, 0, 100, 100, 100, 0, 0, 0),
|
||||
ROUNDED_RECT_INIT_UNIFORM(0, 0, 100, 100, 0, 0, 100, 0),
|
||||
GSK_INTERSECTION_NONEMPTY,
|
||||
ROUNDED_RECT_INIT_UNIFORM(0, 0, 100, 100, 100, 0, 100, 0),
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT_UNIFORM(0, 0, 100, 100, 100, 0, 0, 0),
|
||||
ROUNDED_RECT_INIT_UNIFORM(-20, -20, 100, 100, 0, 0, 100, 0),
|
||||
GSK_INTERSECTION_NOT_REPRESENTABLE,
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT_UNIFORM(0, 0, 50, 50, 0, 0, 50, 0),
|
||||
ROUNDED_RECT_INIT_UNIFORM(0, 0, 20, 20, 20, 0, 0, 0),
|
||||
GSK_INTERSECTION_NOT_REPRESENTABLE, /* FIXME: should be empty */
|
||||
},
|
||||
{
|
||||
ROUNDED_RECT_INIT_UNIFORM(0, 0, 50, 50, 0, 0, 50, 0),
|
||||
ROUNDED_RECT_INIT_UNIFORM(0, 0, 21, 21, 21, 0, 0, 0),
|
||||
GSK_INTERSECTION_NOT_REPRESENTABLE,
|
||||
},
|
||||
};
|
||||
gsize i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (test); i++)
|
||||
{
|
||||
GskRoundedRect out;
|
||||
GskRoundedRectIntersection res;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_test_message ("intersection test %zu", i);
|
||||
|
||||
memset (&out, 0, sizeof (GskRoundedRect));
|
||||
|
||||
res = gsk_rounded_rect_intersection (&test[i].a, &test[i].b, &out);
|
||||
g_assert_cmpint (res, ==, test[i].result);
|
||||
if (res == GSK_INTERSECTION_NONEMPTY)
|
||||
{
|
||||
if (!gsk_rounded_rect_equal (&out, &test[i].expected))
|
||||
{
|
||||
char *a = gsk_rounded_rect_to_string (&test[i].a);
|
||||
char *b = gsk_rounded_rect_to_string (&test[i].b);
|
||||
char *expected = gsk_rounded_rect_to_string (&test[i].expected);
|
||||
char *result = gsk_rounded_rect_to_string (&out);
|
||||
g_test_message (" A = %s\n"
|
||||
" B = %s\n"
|
||||
"expected %s\n"
|
||||
" got %s\n",
|
||||
a, b, expected, result);
|
||||
}
|
||||
g_assert_true (gsk_rounded_rect_equal (&out, &test[i].expected));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
@ -246,6 +392,7 @@ main (int argc,
|
||||
g_test_add_func ("/rounded-rect/is-circular", test_is_circular);
|
||||
g_test_add_func ("/rounded-rect/to-float", test_to_float);
|
||||
g_test_add_func ("/rounded-rect/intersect-with-rect", test_intersect_with_rect);
|
||||
g_test_add_func ("/rounded-rect/intersect", test_intersect);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user