[PATCH 1/2] drm/vkms: Cache composer line buffers in vkms_output
From: oushixiong1025
Date: Thu Aug 20 2026 - 04:32:33 EST
From: Shixiong Ou <oushixiong@xxxxxxxxxx>
compose_active_planes() kvmalloc/kvfree two line buffers every vblank
frame, but their size depends only on hdisplay which changes only on
modeset. Cache them in vkms_output and reallocate only when the width
changes, avoiding repeated alloc/free overhead.
Register a drmm action to free the buffers when the device is released.
Signed-off-by: Shixiong Ou <oushixiong@xxxxxxxxxx>
---
drivers/gpu/drm/vkms/vkms_composer.c | 44 ++++++++++++++++------------
drivers/gpu/drm/vkms/vkms_crtc.c | 12 ++++++++
drivers/gpu/drm/vkms/vkms_drv.h | 7 +++++
3 files changed, 45 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index 83d217085ad0..f3fb203946e8 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -541,11 +541,11 @@ static int check_iosys_map(struct vkms_crtc_state *crtc_state)
static int compose_active_planes(struct vkms_writeback_job *active_wb,
struct vkms_crtc_state *crtc_state,
+ struct vkms_output *out,
u32 *crc32)
{
size_t line_width, pixel_size = sizeof(struct pixel_argb_u16);
struct line_buffer output_buffer, stage_buffer;
- int ret = 0;
/*
* This check exists so we can call `crc32_le` for the entire line
@@ -565,27 +565,35 @@ static int compose_active_planes(struct vkms_writeback_job *active_wb,
stage_buffer.n_pixels = line_width;
output_buffer.n_pixels = line_width;
- stage_buffer.pixels = kvmalloc(line_width * pixel_size, GFP_KERNEL);
- if (!stage_buffer.pixels) {
- DRM_ERROR("Cannot allocate memory for the output line buffer");
- return -ENOMEM;
- }
+ if (out->composer_buffer_width != line_width) {
+ kvfree(out->composer_stage_buffer);
+ kvfree(out->composer_output_buffer);
+ out->composer_buffer_width = 0;
+
+ out->composer_stage_buffer = kvmalloc(line_width * pixel_size, GFP_KERNEL);
+ if (!out->composer_stage_buffer) {
+ DRM_ERROR("Cannot allocate memory for the output line buffer");
+ return -ENOMEM;
+ }
+
+ out->composer_output_buffer = kvmalloc(line_width * pixel_size, GFP_KERNEL);
+ if (!out->composer_output_buffer) {
+ DRM_ERROR("Cannot allocate memory for intermediate line buffer");
+ kvfree(out->composer_stage_buffer);
+ out->composer_stage_buffer = NULL;
+ return -ENOMEM;
+ }
- output_buffer.pixels = kvmalloc(line_width * pixel_size, GFP_KERNEL);
- if (!output_buffer.pixels) {
- DRM_ERROR("Cannot allocate memory for intermediate line buffer");
- ret = -ENOMEM;
- goto free_stage_buffer;
+ out->composer_buffer_width = line_width;
}
+ stage_buffer.pixels = out->composer_stage_buffer;
+ output_buffer.pixels = out->composer_output_buffer;
+
blend(active_wb, crtc_state, crc32, &stage_buffer,
&output_buffer, line_width * pixel_size);
- kvfree(output_buffer.pixels);
-free_stage_buffer:
- kvfree(stage_buffer.pixels);
-
- return ret;
+ return 0;
}
/**
@@ -644,9 +652,9 @@ void vkms_composer_worker(struct work_struct *work)
return;
if (wb_pending)
- ret = compose_active_planes(active_wb, crtc_state, &crc32);
+ ret = compose_active_planes(active_wb, crtc_state, out, &crc32);
else
- ret = compose_active_planes(NULL, crtc_state, &crc32);
+ ret = compose_active_planes(NULL, crtc_state, out, &crc32);
if (ret)
return;
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
index 079abfba427d..6e03c9a1fbd8 100644
--- a/drivers/gpu/drm/vkms/vkms_crtc.c
+++ b/drivers/gpu/drm/vkms/vkms_crtc.c
@@ -13,6 +13,14 @@
#include "vkms_drv.h"
+static void vkms_composer_buffers_release(struct drm_device *dev, void *data)
+{
+ struct vkms_output *out = data;
+
+ kvfree(out->composer_stage_buffer);
+ kvfree(out->composer_output_buffer);
+}
+
static bool vkms_crtc_handle_vblank_timeout(struct drm_crtc *crtc)
{
struct vkms_output *output = drm_crtc_to_vkms_output(crtc);
@@ -237,5 +245,9 @@ struct vkms_output *vkms_crtc_init(struct drm_device *dev, struct drm_plane *pri
if (IS_ERR(vkms_out->composer_workq))
return ERR_CAST(vkms_out->composer_workq);
+ ret = drmm_add_action_or_reset(dev, vkms_composer_buffers_release, vkms_out);
+ if (ret)
+ return ERR_PTR(ret);
+
return vkms_out;
}
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index 0933e4ce0ff0..e6d58b396451 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -214,6 +214,9 @@ struct vkms_crtc_state {
* writeback)
* @composer_state: Protected by @lock, current state of this VKMS output
* @composer_lock: Lock used internally to protect @composer_state members
+ * @composer_stage_buffer: Cached line buffer for plane pixel read and pre-blend transform
+ * @composer_output_buffer: Cached line buffer for blending output
+ * @composer_buffer_width: Current allocated width of the cached buffers (in pixels)
*/
struct vkms_output {
struct drm_crtc crtc;
@@ -226,6 +229,10 @@ struct vkms_output {
struct vkms_crtc_state *composer_state;
spinlock_t composer_lock;
+
+ struct pixel_argb_u16 *composer_stage_buffer;
+ struct pixel_argb_u16 *composer_output_buffer;
+ size_t composer_buffer_width;
};
struct vkms_config;
--
2.25.1
No virus found
Checked by Hillstone Network AntiVirus