From 953025763d1421605939479b2e9c070f03e428c1 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Sun, 30 Aug 2020 10:19:58 -0400 Subject: drm/vkms: Decouple crc operations from composer In the vkms_composer.c, some of the functions related to CRC and compose have interdependence between each other. This patch reworks some functions inside vkms_composer to make crc and composer computation decoupled. This patch is preparation work for making vkms able to support new features. Tested-by: Melissa Wen Signed-off-by: Rodrigo Siqueira Reviewed-by: Melissa Wen Link: https://patchwork.freedesktop.org/patch/msgid/20200830142000.146706-2-rodrigosiqueiramelo@gmail.com --- drivers/gpu/drm/vkms/vkms_composer.c | 49 +++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm/vkms/vkms_composer.c') diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index eaecc5a6c5db..f67d1baf1942 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -131,35 +131,31 @@ static void compose_cursor(struct vkms_composer *cursor_composer, primary_composer, cursor_composer); } -static uint32_t _vkms_get_crc(struct vkms_composer *primary_composer, - struct vkms_composer *cursor_composer) +static int compose_planes(void **vaddr_out, + struct vkms_composer *primary_composer, + struct vkms_composer *cursor_composer) { struct drm_framebuffer *fb = &primary_composer->fb; struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0); struct vkms_gem_object *vkms_obj = drm_gem_to_vkms_gem(gem_obj); - void *vaddr_out = kzalloc(vkms_obj->gem.size, GFP_KERNEL); - u32 crc = 0; - if (!vaddr_out) { - DRM_ERROR("Failed to allocate memory for output frame."); - return 0; + if (!*vaddr_out) { + *vaddr_out = kzalloc(vkms_obj->gem.size, GFP_KERNEL); + if (!*vaddr_out) { + DRM_ERROR("Cannot allocate memory for output frame."); + return -ENOMEM; + } } - if (WARN_ON(!vkms_obj->vaddr)) { - kfree(vaddr_out); - return crc; - } + if (WARN_ON(!vkms_obj->vaddr)) + return -EINVAL; - memcpy(vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size); + memcpy(*vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size); if (cursor_composer) - compose_cursor(cursor_composer, primary_composer, vaddr_out); + compose_cursor(cursor_composer, primary_composer, *vaddr_out); - crc = compute_crc(vaddr_out, primary_composer); - - kfree(vaddr_out); - - return crc; + return 0; } /** @@ -180,9 +176,11 @@ void vkms_composer_worker(struct work_struct *work) struct vkms_output *out = drm_crtc_to_vkms_output(crtc); struct vkms_composer *primary_composer = NULL; struct vkms_composer *cursor_composer = NULL; + void *vaddr_out = NULL; u32 crc32 = 0; u64 frame_start, frame_end; bool crc_pending; + int ret; spin_lock_irq(&out->composer_lock); frame_start = crtc_state->frame_start; @@ -206,14 +204,25 @@ void vkms_composer_worker(struct work_struct *work) if (crtc_state->num_active_planes == 2) cursor_composer = crtc_state->active_planes[1]->composer; - if (primary_composer) - crc32 = _vkms_get_crc(primary_composer, cursor_composer); + if (!primary_composer) + return; + + ret = compose_planes(&vaddr_out, primary_composer, cursor_composer); + if (ret) { + if (ret == -EINVAL) + kfree(vaddr_out); + return; + } + + crc32 = compute_crc(vaddr_out, primary_composer); /* * The worker can fall behind the vblank hrtimer, make sure we catch up. */ while (frame_start <= frame_end) drm_crtc_add_crc_entry(crtc, true, frame_start++, &crc32); + + kfree(vaddr_out); } static const char * const pipe_crc_sources[] = {"auto"}; -- cgit v1.2.3 From 60cc20214cedaa5128005a6ccf38c4f37242cf5b Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Sun, 30 Aug 2020 10:19:59 -0400 Subject: drm/vkms: Compute CRC without change input data This commit decouples pixel manipulation from compute_crc() for avoiding any pixel change during the CRC calculation. This commits represents a preparation work for making VKMS able to support the writeback feature. Change in V5 (Melissa): - Rebase and drop bitmap for alpha Change in V4 (Emil): - Move bitmap_clear operation and comments to get_pixel function Signed-off-by: Rodrigo Siqueira Reviewed-by: Melissa Wen Link: https://patchwork.freedesktop.org/patch/msgid/20200830142000.146706-3-rodrigosiqueiramelo@gmail.com --- drivers/gpu/drm/vkms/vkms_composer.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/vkms/vkms_composer.c') diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index f67d1baf1942..c5b32fe5870f 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -9,31 +9,41 @@ #include "vkms_drv.h" +static u32 get_pixel_from_buffer(int x, int y, const u8 *buffer, + const struct vkms_composer *composer) +{ + u32 pixel; + int src_offset = composer->offset + (y * composer->pitch) + + (x * composer->cpp); + + pixel = *(u32 *)&buffer[src_offset]; + + return pixel; +} + /** * compute_crc - Compute CRC value on output frame * - * @vaddr_out: address to final framebuffer + * @vaddr: address to final framebuffer * @composer: framebuffer's metadata * * returns CRC value computed using crc32 on the visible portion of * the final framebuffer at vaddr_out */ -static uint32_t compute_crc(void *vaddr_out, struct vkms_composer *composer) +static uint32_t compute_crc(const u8 *vaddr, + const struct vkms_composer *composer) { - int i, j, src_offset; + int x, y; + u32 crc = 0, pixel = 0; int x_src = composer->src.x1 >> 16; int y_src = composer->src.y1 >> 16; int h_src = drm_rect_height(&composer->src) >> 16; int w_src = drm_rect_width(&composer->src) >> 16; - u32 crc = 0; - - for (i = y_src; i < y_src + h_src; ++i) { - for (j = x_src; j < x_src + w_src; ++j) { - src_offset = composer->offset - + (i * composer->pitch) - + (j * composer->cpp); - crc = crc32_le(crc, vaddr_out + src_offset, - sizeof(u32)); + + for (y = y_src; y < y_src + h_src; ++y) { + for (x = x_src; x < x_src + w_src; ++x) { + pixel = get_pixel_from_buffer(x, y, vaddr, composer); + crc = crc32_le(crc, (void *)&pixel, sizeof(u32)); } } -- cgit v1.2.3 From dbd9d80c1b2e033d5ec2d00add89a4f18f6899eb Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Sun, 30 Aug 2020 10:20:00 -0400 Subject: drm/vkms: Add support for writeback This patch implements the necessary functions to add writeback support for vkms. This feature is useful for testing compositors if you don't have hardware with writeback support. Change in V4 (Emil and Melissa): - Move signal completion above drm_crtc_add_crc_entry() - Make writeback always available - Use appropriate namespace - Drop fb check in vkms_wb_atomic_commit - Make vkms_set_composer visible for writeback code - Enable composer operation on prepare_job and disable it on cleanup_job - Drop extra space at the end of the file - Rebase Change in V3 (Daniel): - If writeback is enabled, compose everything into the writeback buffer instead of CRC private buffer - Guarantees that the CRC will match exactly what we have in the writeback buffer. Change in V2: - Rework signal completion (Brian) - Integrates writeback with active_planes (Daniel) - Compose cursor (Daniel) Signed-off-by: Rodrigo Siqueira Reviewed-by: Liviu Dudau Link: https://patchwork.freedesktop.org/patch/msgid/20200830142000.146706-4-rodrigosiqueiramelo@gmail.com --- drivers/gpu/drm/vkms/vkms_composer.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/vkms/vkms_composer.c') diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index c5b32fe5870f..33c031f27c2c 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -186,16 +186,17 @@ void vkms_composer_worker(struct work_struct *work) struct vkms_output *out = drm_crtc_to_vkms_output(crtc); struct vkms_composer *primary_composer = NULL; struct vkms_composer *cursor_composer = NULL; + bool crc_pending, wb_pending; void *vaddr_out = NULL; u32 crc32 = 0; u64 frame_start, frame_end; - bool crc_pending; int ret; spin_lock_irq(&out->composer_lock); frame_start = crtc_state->frame_start; frame_end = crtc_state->frame_end; crc_pending = crtc_state->crc_pending; + wb_pending = crtc_state->wb_pending; crtc_state->frame_start = 0; crtc_state->frame_end = 0; crtc_state->crc_pending = false; @@ -217,22 +218,32 @@ void vkms_composer_worker(struct work_struct *work) if (!primary_composer) return; + if (wb_pending) + vaddr_out = crtc_state->active_writeback; + ret = compose_planes(&vaddr_out, primary_composer, cursor_composer); if (ret) { - if (ret == -EINVAL) + if (ret == -EINVAL && !wb_pending) kfree(vaddr_out); return; } crc32 = compute_crc(vaddr_out, primary_composer); + if (wb_pending) { + drm_writeback_signal_completion(&out->wb_connector, 0); + spin_lock_irq(&out->composer_lock); + crtc_state->wb_pending = false; + spin_unlock_irq(&out->composer_lock); + } else { + kfree(vaddr_out); + } + /* * The worker can fall behind the vblank hrtimer, make sure we catch up. */ while (frame_start <= frame_end) drm_crtc_add_crc_entry(crtc, true, frame_start++, &crc32); - - kfree(vaddr_out); } static const char * const pipe_crc_sources[] = {"auto"}; @@ -275,7 +286,7 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const char *src_name, return 0; } -static void vkms_set_composer(struct vkms_output *out, bool enabled) +void vkms_set_composer(struct vkms_output *out, bool enabled) { bool old_enabled; -- cgit v1.2.3