forked from Minki/linux
drm: vkms: Supports to the case where primary plane doesn't match the CRTC
We will remove the current assumption that the primary plane has the same size and position as CRTC and that the primary plane is the bottom-most in zpos order, or is even enabled. At least as far as the blending machinery is concerned. For that we will add CRTC dimension information to `vkms_crtc_state` and add a opaque black backgound color. Because now we need to fill the background, we had a loss in performance with this change. Results running the IGT[1] test `igt@kms_cursor_crc@pipe-a-cursor-512x512-onscreen` ten times: | Frametime | |:--------------------------------------------:| | Implementation | Previous | This commit | |:---------------:|:---------:|:--------------:| | frametime range | 5~18 ms | 10~22 ms | | Average | 8.47 ms | 12.32 ms | [1] IGT commit id: bc3f6833a12221a46659535dac06ebb312490eb4 V6: Improve the commit description (Pekka Paalanen). Update some comments (Pekka Paalanen). Remove some fields from `vkms_crtc_state` and move where some variables are set (Pekka Paalanen). Reviewed-by: Melissa Wen <mwen@igalia.com> Signed-off-by: Igor Torrente <igormtorrente@gmail.com> Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220905190811.25024-8-igormtorrente@gmail.com
This commit is contained in:
parent
8ba1648567
commit
bc0d7fdefe
@ -121,8 +121,7 @@ There's lots of plane features we could add support for:
|
||||
- ARGB format on primary plane: blend the primary plane into background with
|
||||
translucent alpha.
|
||||
|
||||
- Support when the primary plane isn't exactly matching the output size: blend
|
||||
the primary plane into the black background.
|
||||
- Add background color KMS property[Good to get started].
|
||||
|
||||
- Full alpha blending on all planes.
|
||||
|
||||
|
@ -61,6 +61,13 @@ static bool check_y_limit(struct vkms_frame_info *frame_info, int y)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void fill_background(const struct pixel_argb_u16 *background_color,
|
||||
struct line_buffer *output_buffer)
|
||||
{
|
||||
for (size_t i = 0; i < output_buffer->n_pixels; i++)
|
||||
output_buffer->pixels[i] = *background_color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @wb_frame_info: The writeback frame buffer metadata
|
||||
* @crtc_state: The crtc state
|
||||
@ -78,21 +85,17 @@ static void blend(struct vkms_writeback_job *wb,
|
||||
struct line_buffer *output_buffer, size_t row_size)
|
||||
{
|
||||
struct vkms_plane_state **plane = crtc_state->active_planes;
|
||||
struct vkms_frame_info *primary_plane_info = plane[0]->frame_info;
|
||||
u32 n_active_planes = crtc_state->num_active_planes;
|
||||
|
||||
int y_dst = primary_plane_info->dst.y1;
|
||||
int h_dst = drm_rect_height(&primary_plane_info->dst);
|
||||
int y_limit = y_dst + h_dst;
|
||||
const struct pixel_argb_u16 background_color = { .a = 0xffff };
|
||||
|
||||
for (size_t y = y_dst; y < y_limit; y++) {
|
||||
plane[0]->plane_read(output_buffer, primary_plane_info, y);
|
||||
size_t crtc_y_limit = crtc_state->base.crtc->mode.vdisplay;
|
||||
|
||||
/* If there are other planes besides primary, we consider the active
|
||||
* planes should be in z-order and compose them associatively:
|
||||
* ((primary <- overlay) <- cursor)
|
||||
*/
|
||||
for (size_t i = 1; i < n_active_planes; i++) {
|
||||
for (size_t y = 0; y < crtc_y_limit; y++) {
|
||||
fill_background(&background_color, output_buffer);
|
||||
|
||||
/* The active planes are composed associatively in z-order. */
|
||||
for (size_t i = 0; i < n_active_planes; i++) {
|
||||
if (!check_y_limit(plane[i]->frame_info, y))
|
||||
continue;
|
||||
|
||||
@ -124,14 +127,24 @@ static int check_format_funcs(struct vkms_crtc_state *crtc_state,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_iosys_map(struct vkms_crtc_state *crtc_state)
|
||||
{
|
||||
struct vkms_plane_state **plane_state = crtc_state->active_planes;
|
||||
u32 n_active_planes = crtc_state->num_active_planes;
|
||||
|
||||
for (size_t i = 0; i < n_active_planes; i++)
|
||||
if (iosys_map_is_null(&plane_state[i]->frame_info->map[0]))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compose_active_planes(struct vkms_writeback_job *active_wb,
|
||||
struct vkms_crtc_state *crtc_state,
|
||||
u32 *crc32)
|
||||
{
|
||||
size_t line_width, pixel_size = sizeof(struct pixel_argb_u16);
|
||||
struct vkms_frame_info *primary_plane_info = NULL;
|
||||
struct line_buffer output_buffer, stage_buffer;
|
||||
struct vkms_plane_state *act_plane = NULL;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
@ -142,22 +155,13 @@ static int compose_active_planes(struct vkms_writeback_job *active_wb,
|
||||
*/
|
||||
static_assert(sizeof(struct pixel_argb_u16) == 8);
|
||||
|
||||
if (crtc_state->num_active_planes >= 1) {
|
||||
act_plane = crtc_state->active_planes[0];
|
||||
if (act_plane->base.base.plane->type == DRM_PLANE_TYPE_PRIMARY)
|
||||
primary_plane_info = act_plane->frame_info;
|
||||
}
|
||||
|
||||
if (!primary_plane_info)
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(iosys_map_is_null(&primary_plane_info->map[0])))
|
||||
if (WARN_ON(check_iosys_map(crtc_state)))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(check_format_funcs(crtc_state, active_wb)))
|
||||
return -EINVAL;
|
||||
|
||||
line_width = drm_rect_width(&primary_plane_info->dst);
|
||||
line_width = crtc_state->base.crtc->mode.hdisplay;
|
||||
stage_buffer.n_pixels = line_width;
|
||||
output_buffer.n_pixels = line_width;
|
||||
|
||||
@ -174,13 +178,6 @@ static int compose_active_planes(struct vkms_writeback_job *active_wb,
|
||||
goto free_stage_buffer;
|
||||
}
|
||||
|
||||
if (active_wb) {
|
||||
struct vkms_frame_info *wb_frame_info = &active_wb->wb_frame_info;
|
||||
|
||||
wb_frame_info->src = primary_plane_info->src;
|
||||
wb_frame_info->dst = primary_plane_info->dst;
|
||||
}
|
||||
|
||||
blend(active_wb, crtc_state, crc32, &stage_buffer,
|
||||
&output_buffer, line_width * pixel_size);
|
||||
|
||||
|
@ -123,6 +123,8 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn,
|
||||
struct drm_connector_state *conn_state = wb_conn->base.state;
|
||||
struct vkms_crtc_state *crtc_state = output->composer_state;
|
||||
struct drm_framebuffer *fb = connector_state->writeback_job->fb;
|
||||
u16 crtc_height = crtc_state->base.crtc->mode.vdisplay;
|
||||
u16 crtc_width = crtc_state->base.crtc->mode.hdisplay;
|
||||
struct vkms_writeback_job *active_wb;
|
||||
struct vkms_frame_info *wb_frame_info;
|
||||
u32 wb_format = fb->format->format;
|
||||
@ -144,6 +146,8 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn,
|
||||
spin_unlock_irq(&output->composer_lock);
|
||||
drm_writeback_queue_job(wb_conn, connector_state);
|
||||
active_wb->wb_write = get_line_to_frame_function(wb_format);
|
||||
drm_rect_init(&wb_frame_info->src, 0, 0, crtc_width, crtc_height);
|
||||
drm_rect_init(&wb_frame_info->dst, 0, 0, crtc_width, crtc_height);
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs vkms_wb_conn_helper_funcs = {
|
||||
|
Loading…
Reference in New Issue
Block a user