mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-25 22:25:58 +01:00
render/vulkan: constrain blend to output subpass to redrawn region
This commit only applies to the render pass API.
This commit is contained in:
parent
d180f4d9b3
commit
e0adaaffb6
2 changed files with 57 additions and 4 deletions
|
@ -10,6 +10,7 @@
|
||||||
#include <wlr/render/drm_format_set.h>
|
#include <wlr/render/drm_format_set.h>
|
||||||
#include <wlr/render/interface.h>
|
#include <wlr/render/interface.h>
|
||||||
#include <wlr/util/addon.h>
|
#include <wlr/util/addon.h>
|
||||||
|
#include "util/rect_union.h"
|
||||||
|
|
||||||
struct wlr_vk_descriptor_pool;
|
struct wlr_vk_descriptor_pool;
|
||||||
struct wlr_vk_texture;
|
struct wlr_vk_texture;
|
||||||
|
@ -334,6 +335,7 @@ struct wlr_vk_render_pass {
|
||||||
struct wlr_vk_renderer *renderer;
|
struct wlr_vk_renderer *renderer;
|
||||||
struct wlr_vk_render_buffer *render_buffer;
|
struct wlr_vk_render_buffer *render_buffer;
|
||||||
struct wlr_vk_command_buffer *command_buffer;
|
struct wlr_vk_command_buffer *command_buffer;
|
||||||
|
struct rect_union updated_region;
|
||||||
VkPipeline bound_pipeline;
|
VkPipeline bound_pipeline;
|
||||||
float projection[9];
|
float projection[9];
|
||||||
bool failed;
|
bool failed;
|
||||||
|
|
|
@ -108,10 +108,16 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS, renderer->output_pipe_layout,
|
VK_PIPELINE_BIND_POINT_GRAPHICS, renderer->output_pipe_layout,
|
||||||
0, 1, &render_buffer->blend_descriptor_set, 0, NULL);
|
0, 1, &render_buffer->blend_descriptor_set, 0, NULL);
|
||||||
|
|
||||||
vkCmdSetScissor(render_cb->vk, 0, 1, &(VkRect2D){
|
const pixman_region32_t *clip = rect_union_evaluate(&pass->updated_region);
|
||||||
.extent = { width, height },
|
int clip_rects_len;
|
||||||
});
|
const pixman_box32_t *clip_rects = pixman_region32_rectangles(
|
||||||
vkCmdDraw(render_cb->vk, 4, 1, 0, 0);
|
clip, &clip_rects_len);
|
||||||
|
for (int i = 0; i < clip_rects_len; i++) {
|
||||||
|
VkRect2D rect;
|
||||||
|
convert_pixman_box_to_vk_rect(&clip_rects[i], &rect);
|
||||||
|
vkCmdSetScissor(render_cb->vk, 0, 1, &rect);
|
||||||
|
vkCmdDraw(render_cb->vk, 4, 1, 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vkCmdEndRenderPass(render_cb->vk);
|
vkCmdEndRenderPass(render_cb->vk);
|
||||||
|
@ -388,6 +394,7 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_buffer_unlock(render_buffer->wlr_buffer);
|
wlr_buffer_unlock(render_buffer->wlr_buffer);
|
||||||
|
rect_union_finish(&pass->updated_region);
|
||||||
free(pass);
|
free(pass);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -396,6 +403,7 @@ error:
|
||||||
vulkan_reset_command_buffer(stage_cb);
|
vulkan_reset_command_buffer(stage_cb);
|
||||||
vulkan_reset_command_buffer(render_cb);
|
vulkan_reset_command_buffer(render_cb);
|
||||||
wlr_buffer_unlock(render_buffer->wlr_buffer);
|
wlr_buffer_unlock(render_buffer->wlr_buffer);
|
||||||
|
rect_union_finish(&pass->updated_region);
|
||||||
free(pass);
|
free(pass);
|
||||||
|
|
||||||
if (device_lost) {
|
if (device_lost) {
|
||||||
|
@ -405,6 +413,21 @@ error:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void render_pass_mark_box_updated(struct wlr_vk_render_pass *pass,
|
||||||
|
const struct wlr_box *box) {
|
||||||
|
if (!pass->render_buffer->blend_image) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixman_box32_t pixman_box = {
|
||||||
|
.x1 = box->x,
|
||||||
|
.x2 = box->x + box->width,
|
||||||
|
.y1 = box->y,
|
||||||
|
.y2 = box->y + box->height,
|
||||||
|
};
|
||||||
|
rect_union_add(&pass->updated_region, pixman_box);
|
||||||
|
}
|
||||||
|
|
||||||
static void render_pass_add_rect(struct wlr_render_pass *wlr_pass,
|
static void render_pass_add_rect(struct wlr_render_pass *wlr_pass,
|
||||||
const struct wlr_render_rect_options *options) {
|
const struct wlr_render_rect_options *options) {
|
||||||
struct wlr_vk_render_pass *pass = get_render_pass(wlr_pass);
|
struct wlr_vk_render_pass *pass = get_render_pass(wlr_pass);
|
||||||
|
@ -427,6 +450,20 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass,
|
||||||
|
|
||||||
int clip_rects_len;
|
int clip_rects_len;
|
||||||
const pixman_box32_t *clip_rects = pixman_region32_rectangles(&clip, &clip_rects_len);
|
const pixman_box32_t *clip_rects = pixman_region32_rectangles(&clip, &clip_rects_len);
|
||||||
|
// Record regions possibly updated for use in second subpass
|
||||||
|
for (int i = 0; i < clip_rects_len; i++) {
|
||||||
|
struct wlr_box clip_box = {
|
||||||
|
.x = clip_rects[i].x1,
|
||||||
|
.y = clip_rects[i].y1,
|
||||||
|
.width = clip_rects[i].x2 - clip_rects[i].x1,
|
||||||
|
.height = clip_rects[i].y2 - clip_rects[i].y1,
|
||||||
|
};
|
||||||
|
struct wlr_box intersection;
|
||||||
|
if (!wlr_box_intersection(&intersection, &options->box, &clip_box)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
render_pass_mark_box_updated(pass, &intersection);
|
||||||
|
}
|
||||||
|
|
||||||
struct wlr_box box;
|
struct wlr_box box;
|
||||||
wlr_render_rect_options_get_box(options, pass->render_buffer->wlr_buffer, &box);
|
wlr_render_rect_options_get_box(options, pass->render_buffer->wlr_buffer, &box);
|
||||||
|
@ -590,6 +627,18 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
|
||||||
convert_pixman_box_to_vk_rect(&clip_rects[i], &rect);
|
convert_pixman_box_to_vk_rect(&clip_rects[i], &rect);
|
||||||
vkCmdSetScissor(cb, 0, 1, &rect);
|
vkCmdSetScissor(cb, 0, 1, &rect);
|
||||||
vkCmdDraw(cb, 4, 1, 0, 0);
|
vkCmdDraw(cb, 4, 1, 0, 0);
|
||||||
|
|
||||||
|
struct wlr_box clip_box = {
|
||||||
|
.x = clip_rects[i].x1,
|
||||||
|
.y = clip_rects[i].y1,
|
||||||
|
.width = clip_rects[i].x2 - clip_rects[i].x1,
|
||||||
|
.height = clip_rects[i].y2 - clip_rects[i].y1,
|
||||||
|
};
|
||||||
|
struct wlr_box intersection;
|
||||||
|
if (!wlr_box_intersection(&intersection, &dst_box, &clip_box)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
render_pass_mark_box_updated(pass, &intersection);
|
||||||
}
|
}
|
||||||
|
|
||||||
texture->last_used_cb = pass->command_buffer;
|
texture->last_used_cb = pass->command_buffer;
|
||||||
|
@ -610,6 +659,8 @@ struct wlr_vk_render_pass *vulkan_begin_render_pass(struct wlr_vk_renderer *rend
|
||||||
wlr_render_pass_init(&pass->base, &render_pass_impl);
|
wlr_render_pass_init(&pass->base, &render_pass_impl);
|
||||||
pass->renderer = renderer;
|
pass->renderer = renderer;
|
||||||
|
|
||||||
|
rect_union_init(&pass->updated_region);
|
||||||
|
|
||||||
struct wlr_vk_command_buffer *cb = vulkan_acquire_command_buffer(renderer);
|
struct wlr_vk_command_buffer *cb = vulkan_acquire_command_buffer(renderer);
|
||||||
if (cb == NULL) {
|
if (cb == NULL) {
|
||||||
free(pass);
|
free(pass);
|
||||||
|
|
Loading…
Reference in a new issue