|
|
|
@ -60,13 +60,6 @@ static struct wlr_vk_render_format_setup *find_or_create_render_setup(
|
|
|
|
|
struct wlr_vk_renderer *renderer, const struct wlr_vk_format *format,
|
|
|
|
|
bool has_blending_buffer);
|
|
|
|
|
|
|
|
|
|
// https://www.w3.org/Graphics/Color/srgb
|
|
|
|
|
static float color_to_linear(float non_linear) {
|
|
|
|
|
return (non_linear > 0.04045) ?
|
|
|
|
|
pow((non_linear + 0.055) / 1.055, 2.4) :
|
|
|
|
|
non_linear / 12.92;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void mat3_to_mat4(const float mat3[9], float mat4[4][4]) {
|
|
|
|
|
memset(mat4, 0, sizeof(float) * 16);
|
|
|
|
|
mat4[0][0] = mat3[0];
|
|
|
|
@ -1387,125 +1380,6 @@ static void vulkan_end(struct wlr_renderer *wlr_renderer) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool vulkan_render_subtexture_with_matrix(struct wlr_renderer *wlr_renderer,
|
|
|
|
|
struct wlr_texture *wlr_texture, const struct wlr_fbox *box,
|
|
|
|
|
const float matrix[static 9], float alpha) {
|
|
|
|
|
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
|
|
|
|
VkCommandBuffer cb = renderer->current_command_buffer->vk;
|
|
|
|
|
|
|
|
|
|
struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture);
|
|
|
|
|
assert(texture->renderer == renderer);
|
|
|
|
|
if (texture->dmabuf_imported && !texture->owned) {
|
|
|
|
|
// Store this texture in the list of textures that need to be
|
|
|
|
|
// acquired before rendering and released after rendering.
|
|
|
|
|
// We don't do it here immediately since barriers inside
|
|
|
|
|
// a renderpass are suboptimal (would require additional renderpass
|
|
|
|
|
// dependency and potentially multiple barriers) and it's
|
|
|
|
|
// better to issue one barrier for all used textures anyways.
|
|
|
|
|
texture->owned = true;
|
|
|
|
|
assert(texture->foreign_link.prev == NULL);
|
|
|
|
|
assert(texture->foreign_link.next == NULL);
|
|
|
|
|
wl_list_insert(&renderer->foreign_textures, &texture->foreign_link);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct wlr_vk_pipeline *pipe = setup_get_or_create_pipeline(
|
|
|
|
|
renderer->current_render_buffer->render_setup,
|
|
|
|
|
&(struct wlr_vk_pipeline_key) {
|
|
|
|
|
.layout = {
|
|
|
|
|
.ycbcr_format = texture->format->is_ycbcr ? texture->format : NULL,
|
|
|
|
|
},
|
|
|
|
|
.texture_transform = texture->transform,
|
|
|
|
|
});
|
|
|
|
|
if (!pipe) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct wlr_vk_texture_view *view =
|
|
|
|
|
vulkan_texture_get_or_create_view(texture, pipe->layout);
|
|
|
|
|
if (!view) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pipe->vk != renderer->bound_pipe) {
|
|
|
|
|
vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe->vk);
|
|
|
|
|
renderer->bound_pipe = pipe->vk;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
|
|
|
pipe->layout->vk, 0, 1, &view->ds, 0, NULL);
|
|
|
|
|
|
|
|
|
|
float final_matrix[9];
|
|
|
|
|
wlr_matrix_multiply(final_matrix, renderer->projection, matrix);
|
|
|
|
|
|
|
|
|
|
struct wlr_vk_vert_pcr_data vert_pcr_data;
|
|
|
|
|
mat3_to_mat4(final_matrix, vert_pcr_data.mat4);
|
|
|
|
|
|
|
|
|
|
vert_pcr_data.uv_off[0] = box->x / wlr_texture->width;
|
|
|
|
|
vert_pcr_data.uv_off[1] = box->y / wlr_texture->height;
|
|
|
|
|
vert_pcr_data.uv_size[0] = box->width / wlr_texture->width;
|
|
|
|
|
vert_pcr_data.uv_size[1] = box->height / wlr_texture->height;
|
|
|
|
|
|
|
|
|
|
vkCmdPushConstants(cb, pipe->layout->vk,
|
|
|
|
|
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vert_pcr_data), &vert_pcr_data);
|
|
|
|
|
vkCmdPushConstants(cb, pipe->layout->vk,
|
|
|
|
|
VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(vert_pcr_data), sizeof(float),
|
|
|
|
|
&alpha);
|
|
|
|
|
vkCmdDraw(cb, 4, 1, 0, 0);
|
|
|
|
|
texture->last_used_cb = renderer->current_command_buffer;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void vulkan_clear(struct wlr_renderer *wlr_renderer,
|
|
|
|
|
const float color[static 4]) {
|
|
|
|
|
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
|
|
|
|
VkCommandBuffer cb = renderer->current_command_buffer->vk;
|
|
|
|
|
|
|
|
|
|
if (renderer->scissor.extent.width == 0 || renderer->scissor.extent.height == 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkClearAttachment att = {
|
|
|
|
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
|
.colorAttachment = 0u,
|
|
|
|
|
// Input color values are given in srgb space, vulkan expects
|
|
|
|
|
// them in linear space. We explicitly import argb8 render buffers
|
|
|
|
|
// as srgb, vulkan will convert the input values we give here to
|
|
|
|
|
// srgb first.
|
|
|
|
|
// But in other parts of wlroots we just always assume
|
|
|
|
|
// srgb so that's why we have to convert here.
|
|
|
|
|
.clearValue.color.float32 = {
|
|
|
|
|
color_to_linear(color[0]),
|
|
|
|
|
color_to_linear(color[1]),
|
|
|
|
|
color_to_linear(color[2]),
|
|
|
|
|
color[3], // no conversion for alpha
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkClearRect rect = {
|
|
|
|
|
.rect = renderer->scissor,
|
|
|
|
|
.layerCount = 1,
|
|
|
|
|
};
|
|
|
|
|
vkCmdClearAttachments(cb, 1, &att, 1, &rect);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void vulkan_scissor(struct wlr_renderer *wlr_renderer,
|
|
|
|
|
struct wlr_box *box) {
|
|
|
|
|
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
|
|
|
|
VkCommandBuffer cb = renderer->current_command_buffer->vk;
|
|
|
|
|
|
|
|
|
|
uint32_t w = renderer->render_width;
|
|
|
|
|
uint32_t h = renderer->render_height;
|
|
|
|
|
struct wlr_box dst = {0, 0, w, h};
|
|
|
|
|
if (box && !wlr_box_intersection(&dst, box, &dst)) {
|
|
|
|
|
dst = (struct wlr_box) {0, 0, 0, 0}; // empty
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkRect2D rect = (VkRect2D) {{dst.x, dst.y}, {dst.width, dst.height}};
|
|
|
|
|
renderer->scissor = rect;
|
|
|
|
|
vkCmdSetScissor(cb, 0, 1, &rect);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const uint32_t *vulkan_get_shm_texture_formats(
|
|
|
|
|
struct wlr_renderer *wlr_renderer, size_t *len) {
|
|
|
|
|
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
|
|
|
@ -1513,59 +1387,6 @@ static const uint32_t *vulkan_get_shm_texture_formats(
|
|
|
|
|
return renderer->dev->shm_formats;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void vulkan_render_quad_with_matrix(struct wlr_renderer *wlr_renderer,
|
|
|
|
|
const float color[static 4], const float matrix[static 9]) {
|
|
|
|
|
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
|
|
|
|
VkCommandBuffer cb = renderer->current_command_buffer->vk;
|
|
|
|
|
|
|
|
|
|
struct wlr_vk_pipeline *pipe = setup_get_or_create_pipeline(
|
|
|
|
|
renderer->current_render_buffer->render_setup,
|
|
|
|
|
&(struct wlr_vk_pipeline_key) {
|
|
|
|
|
.source = WLR_VK_SHADER_SOURCE_SINGLE_COLOR,
|
|
|
|
|
.layout = {
|
|
|
|
|
.ycbcr_format = NULL,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
if (!pipe) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pipe->vk != renderer->bound_pipe) {
|
|
|
|
|
vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe->vk);
|
|
|
|
|
renderer->bound_pipe = pipe->vk;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float final_matrix[9];
|
|
|
|
|
wlr_matrix_multiply(final_matrix, renderer->projection, matrix);
|
|
|
|
|
|
|
|
|
|
struct wlr_vk_vert_pcr_data vert_pcr_data;
|
|
|
|
|
mat3_to_mat4(final_matrix, vert_pcr_data.mat4);
|
|
|
|
|
vert_pcr_data.uv_off[0] = 0.f;
|
|
|
|
|
vert_pcr_data.uv_off[1] = 0.f;
|
|
|
|
|
vert_pcr_data.uv_size[0] = 1.f;
|
|
|
|
|
vert_pcr_data.uv_size[1] = 1.f;
|
|
|
|
|
|
|
|
|
|
// Input color values are given in srgb space, shader expects
|
|
|
|
|
// them in linear space. The shader does all computation in linear
|
|
|
|
|
// space and expects in inputs in linear space since it outputs
|
|
|
|
|
// colors in linear space as well (and vulkan then automatically
|
|
|
|
|
// does the conversion for out SRGB render targets).
|
|
|
|
|
// But in other parts of wlroots we just always assume
|
|
|
|
|
// srgb so that's why we have to convert here.
|
|
|
|
|
float linear_color[4];
|
|
|
|
|
linear_color[0] = color_to_linear(color[0]);
|
|
|
|
|
linear_color[1] = color_to_linear(color[1]);
|
|
|
|
|
linear_color[2] = color_to_linear(color[2]);
|
|
|
|
|
linear_color[3] = color[3]; // no conversion for alpha
|
|
|
|
|
|
|
|
|
|
vkCmdPushConstants(cb, pipe->layout->vk,
|
|
|
|
|
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vert_pcr_data), &vert_pcr_data);
|
|
|
|
|
vkCmdPushConstants(cb, pipe->layout->vk,
|
|
|
|
|
VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(vert_pcr_data), sizeof(float) * 4,
|
|
|
|
|
linear_color);
|
|
|
|
|
vkCmdDraw(cb, 4, 1, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const struct wlr_drm_format_set *vulkan_get_dmabuf_texture_formats(
|
|
|
|
|
struct wlr_renderer *wlr_renderer) {
|
|
|
|
|
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
|
|
|
@ -1946,10 +1767,6 @@ static const struct wlr_renderer_impl renderer_impl = {
|
|
|
|
|
.bind_buffer = vulkan_bind_buffer,
|
|
|
|
|
.begin = vulkan_begin,
|
|
|
|
|
.end = vulkan_end,
|
|
|
|
|
.clear = vulkan_clear,
|
|
|
|
|
.scissor = vulkan_scissor,
|
|
|
|
|
.render_subtexture_with_matrix = vulkan_render_subtexture_with_matrix,
|
|
|
|
|
.render_quad_with_matrix = vulkan_render_quad_with_matrix,
|
|
|
|
|
.get_shm_texture_formats = vulkan_get_shm_texture_formats,
|
|
|
|
|
.get_dmabuf_texture_formats = vulkan_get_dmabuf_texture_formats,
|
|
|
|
|
.get_render_formats = vulkan_get_render_formats,
|
|
|
|
|