Commit bc0d7fde authored by Igor Torrente's avatar Igor Torrente Committed by Melissa Wen

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: default avatarMelissa Wen <mwen@igalia.com>
Signed-off-by: default avatarIgor Torrente <igormtorrente@gmail.com>
Signed-off-by: default avatarMelissa Wen <melissa.srw@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220905190811.25024-8-igormtorrente@gmail.com
parent 8ba16485
...@@ -121,8 +121,7 @@ There's lots of plane features we could add support for: ...@@ -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 - ARGB format on primary plane: blend the primary plane into background with
translucent alpha. translucent alpha.
- Support when the primary plane isn't exactly matching the output size: blend - Add background color KMS property[Good to get started].
the primary plane into the black background.
- Full alpha blending on all planes. - Full alpha blending on all planes.
......
...@@ -61,6 +61,13 @@ static bool check_y_limit(struct vkms_frame_info *frame_info, int y) ...@@ -61,6 +61,13 @@ static bool check_y_limit(struct vkms_frame_info *frame_info, int y)
return false; 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 * @wb_frame_info: The writeback frame buffer metadata
* @crtc_state: The crtc state * @crtc_state: The crtc state
...@@ -78,21 +85,17 @@ static void blend(struct vkms_writeback_job *wb, ...@@ -78,21 +85,17 @@ static void blend(struct vkms_writeback_job *wb,
struct line_buffer *output_buffer, size_t row_size) struct line_buffer *output_buffer, size_t row_size)
{ {
struct vkms_plane_state **plane = crtc_state->active_planes; 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; u32 n_active_planes = crtc_state->num_active_planes;
int y_dst = primary_plane_info->dst.y1; const struct pixel_argb_u16 background_color = { .a = 0xffff };
int h_dst = drm_rect_height(&primary_plane_info->dst);
int y_limit = y_dst + h_dst;
for (size_t y = y_dst; y < y_limit; y++) { size_t crtc_y_limit = crtc_state->base.crtc->mode.vdisplay;
plane[0]->plane_read(output_buffer, primary_plane_info, y);
/* If there are other planes besides primary, we consider the active for (size_t y = 0; y < crtc_y_limit; y++) {
* planes should be in z-order and compose them associatively: fill_background(&background_color, output_buffer);
* ((primary <- overlay) <- cursor)
*/ /* The active planes are composed associatively in z-order. */
for (size_t i = 1; i < n_active_planes; i++) { for (size_t i = 0; i < n_active_planes; i++) {
if (!check_y_limit(plane[i]->frame_info, y)) if (!check_y_limit(plane[i]->frame_info, y))
continue; continue;
...@@ -124,14 +127,24 @@ static int check_format_funcs(struct vkms_crtc_state *crtc_state, ...@@ -124,14 +127,24 @@ static int check_format_funcs(struct vkms_crtc_state *crtc_state,
return 0; 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, static int compose_active_planes(struct vkms_writeback_job *active_wb,
struct vkms_crtc_state *crtc_state, struct vkms_crtc_state *crtc_state,
u32 *crc32) u32 *crc32)
{ {
size_t line_width, pixel_size = sizeof(struct pixel_argb_u16); 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 line_buffer output_buffer, stage_buffer;
struct vkms_plane_state *act_plane = NULL;
int ret = 0; int ret = 0;
/* /*
...@@ -142,22 +155,13 @@ static int compose_active_planes(struct vkms_writeback_job *active_wb, ...@@ -142,22 +155,13 @@ static int compose_active_planes(struct vkms_writeback_job *active_wb,
*/ */
static_assert(sizeof(struct pixel_argb_u16) == 8); static_assert(sizeof(struct pixel_argb_u16) == 8);
if (crtc_state->num_active_planes >= 1) { if (WARN_ON(check_iosys_map(crtc_state)))
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])))
return -EINVAL; return -EINVAL;
if (WARN_ON(check_format_funcs(crtc_state, active_wb))) if (WARN_ON(check_format_funcs(crtc_state, active_wb)))
return -EINVAL; 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; stage_buffer.n_pixels = line_width;
output_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, ...@@ -174,13 +178,6 @@ static int compose_active_planes(struct vkms_writeback_job *active_wb,
goto free_stage_buffer; 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, blend(active_wb, crtc_state, crc32, &stage_buffer,
&output_buffer, line_width * pixel_size); &output_buffer, line_width * pixel_size);
......
...@@ -123,6 +123,8 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn, ...@@ -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 drm_connector_state *conn_state = wb_conn->base.state;
struct vkms_crtc_state *crtc_state = output->composer_state; struct vkms_crtc_state *crtc_state = output->composer_state;
struct drm_framebuffer *fb = connector_state->writeback_job->fb; 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_writeback_job *active_wb;
struct vkms_frame_info *wb_frame_info; struct vkms_frame_info *wb_frame_info;
u32 wb_format = fb->format->format; u32 wb_format = fb->format->format;
...@@ -144,6 +146,8 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn, ...@@ -144,6 +146,8 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn,
spin_unlock_irq(&output->composer_lock); spin_unlock_irq(&output->composer_lock);
drm_writeback_queue_job(wb_conn, connector_state); drm_writeback_queue_job(wb_conn, connector_state);
active_wb->wb_write = get_line_to_frame_function(wb_format); 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 = { static const struct drm_connector_helper_funcs vkms_wb_conn_helper_funcs = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment