A frame packing mode describes one eye: hdisplay and vdisplay are the
size of one view, while the frame holds both views and the vertical
blanking between them. drm_mode_get_hv_timing() returns the size of
that frame, vdisplay + vtotal lines for frame packing, and the atomic
helpers already clip the planes to it. The composer still stops at
vdisplay, and the writeback connector refuses a buffer taller than one
eye, so the right eye never reaches the writeback buffer or the CRC.

Use drm_mode_get_hv_timing() for the composed area and for the
writeback buffer. Modes the helper does not enlarge keep their size,
top-and-bottom and side by side (half) included: their eyes share the
frame of the mode.

Assisted-by: LLM
Signed-off-by: Daniel Campos Ramos <[email protected]>
---
 drivers/gpu/drm/vkms/vkms_composer.c  |  9 ++++++---
 drivers/gpu/drm/vkms/vkms_writeback.c | 11 ++++++-----
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index 83d217085a..751b7373c0 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -484,8 +484,9 @@ static void blend(struct vkms_writeback_job *wb,
                .b = DRM_ARGB64_GETB(bgcolor),
        };
 
-       int crtc_y_limit = crtc_state->base.mode.vdisplay;
-       int crtc_x_limit = crtc_state->base.mode.hdisplay;
+       int crtc_x_limit, crtc_y_limit;
+
+       drm_mode_get_hv_timing(&crtc_state->base.mode, &crtc_x_limit, 
&crtc_y_limit);
 
        /*
         * The planes are composed line-by-line to avoid heavy memory usage. It 
is a necessary
@@ -545,6 +546,7 @@ static int compose_active_planes(struct vkms_writeback_job 
*active_wb,
 {
        size_t line_width, pixel_size = sizeof(struct pixel_argb_u16);
        struct line_buffer output_buffer, stage_buffer;
+       int crtc_width, crtc_height;
        int ret = 0;
 
        /*
@@ -561,7 +563,8 @@ static int compose_active_planes(struct vkms_writeback_job 
*active_wb,
        if (WARN_ON(check_format_funcs(crtc_state, active_wb)))
                return -EINVAL;
 
-       line_width = crtc_state->base.mode.hdisplay;
+       drm_mode_get_hv_timing(&crtc_state->base.mode, &crtc_width, 
&crtc_height);
+       line_width = crtc_width;
        stage_buffer.n_pixels = line_width;
        output_buffer.n_pixels = line_width;
 
diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c 
b/drivers/gpu/drm/vkms/vkms_writeback.c
index ecf29a2c0c..40ee142e0e 100644
--- a/drivers/gpu/drm/vkms/vkms_writeback.c
+++ b/drivers/gpu/drm/vkms/vkms_writeback.c
@@ -38,7 +38,7 @@ static int vkms_wb_atomic_check(struct drm_connector 
*connector,
                drm_atomic_get_new_connector_state(state, connector);
        struct drm_crtc_state *crtc_state;
        struct drm_framebuffer *fb;
-       const struct drm_display_mode *mode;
+       int width, height;
        int ret;
 
        if (!conn_state->writeback_job || !conn_state->writeback_job->fb)
@@ -48,10 +48,10 @@ static int vkms_wb_atomic_check(struct drm_connector 
*connector,
                return 0;
 
        crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
-       mode = &crtc_state->mode;
+       drm_mode_get_hv_timing(&crtc_state->mode, &width, &height);
 
        fb = conn_state->writeback_job->fb;
-       if (fb->width != mode->hdisplay || fb->height != mode->vdisplay) {
+       if (fb->width != width || fb->height != height) {
                DRM_DEBUG_KMS("Invalid framebuffer size %ux%u\n",
                              fb->width, fb->height);
                return -EINVAL;
@@ -132,15 +132,16 @@ 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.mode.vdisplay;
-       u16 crtc_width = crtc_state->base.mode.hdisplay;
        struct vkms_writeback_job *active_wb;
        struct vkms_frame_info *wb_frame_info;
        u32 wb_format = fb->format->format;
+       int crtc_width, crtc_height;
 
        if (!conn_state)
                return;
 
+       drm_mode_get_hv_timing(&crtc_state->base.mode, &crtc_width, 
&crtc_height);
+
        vkms_set_composer(output, true);
 
        active_wb = conn_state->writeback_job->priv;

Reply via email to