From d2b4699512b316bae73d78ae9149671011a2b086 Mon Sep 17 00:00:00 2001 From: Hyun Kwon Date: Thu, 10 Nov 2016 15:09:47 -0800 Subject: [PATCH 7/9] kmssink: Calculate the offset for framebuffer planes using pitch - For multi-planar format framebuffers, the pitch needs to be considered when calculating the offset. As an example, the offset for the second plane of semi-planar framebuffer should be pitch x height. - Initially, the offset was calculated using width, which could be smaller than pitch and resulted in wrong offset. - Distorted stripe was displayed on the screen as the display controller read the second plane from incorrect address. Signed-off-by: Hyun Kwon Upstream Status: Pending --- sys/kms/gstkmsallocator.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/sys/kms/gstkmsallocator.c b/sys/kms/gstkmsallocator.c index e031848..d368397 100644 --- a/sys/kms/gstkmsallocator.c +++ b/sys/kms/gstkmsallocator.c @@ -126,6 +126,11 @@ gst_kms_allocator_memory_create (GstKMSAllocator * allocator, KMS_HEIGHT, GST_VIDEO_INFO_HEIGHT (vinfo), KMS_TERMINATE_PROP_LIST, }; + guint i, virt_height = 0; + + for (i = 0; i < vinfo->finfo->n_planes; i++) + virt_height += GST_VIDEO_INFO_HEIGHT (vinfo) >> vinfo->finfo->h_sub[i]; + attrs[3] = virt_height; if (kmsmem->bo) return TRUE; @@ -304,6 +309,7 @@ gst_kms_allocator_add_fb (GstKMSAllocator * alloc, GstKMSMemory * kmsmem, int i, ret; gint num_planes = GST_VIDEO_INFO_N_PLANES (vinfo); guint32 w, h, fmt, pitch = 0, bo_handles[4] = { 0, }; + guint32 prev_offset = 0, prev_size = 0; guint32 offsets[4] = { 0, }; guint32 pitches[4] = { 0, }; @@ -331,9 +337,16 @@ gst_kms_allocator_add_fb (GstKMSAllocator * alloc, GstKMSMemory * kmsmem, bo_handles[1], bo_handles[2], bo_handles[3]); for (i = 0; i < num_planes; i++) { - offsets[i] = mem_offsets[i]; - if (pitch) + if (pitch) { GST_VIDEO_INFO_PLANE_STRIDE (vinfo, i) = pitch; + offsets[i] = prev_offset + prev_size; + GST_VIDEO_INFO_PLANE_OFFSET(vinfo, i) = offsets[i]; + prev_offset = offsets[i]; + prev_size = pitch * h >> vinfo->finfo->h_sub[i]; + GST_VIDEO_INFO_SIZE(vinfo) = prev_offset + prev_size; + } else { + offsets[i] = mem_offsets[i]; + } pitches[i] = GST_VIDEO_INFO_PLANE_STRIDE (vinfo, i); GST_DEBUG_OBJECT (alloc, "Create FB plane %i with stride %u and offset %u", i, pitches[i], offsets[i]); @@ -360,9 +373,6 @@ gst_kms_allocator_alloc_empty (GstAllocator * allocator, GstVideoInfo * vinfo) return NULL; mem = GST_MEMORY_CAST (kmsmem); - gst_memory_init (mem, GST_MEMORY_FLAG_NO_SHARE, allocator, NULL, - GST_VIDEO_INFO_SIZE (vinfo), 0, 0, GST_VIDEO_INFO_SIZE (vinfo)); - return mem; } @@ -384,6 +394,10 @@ gst_kms_allocator_bo_alloc (GstAllocator * allocator, GstVideoInfo * vinfo) if (!gst_kms_allocator_add_fb (alloc, kmsmem, vinfo->offset, vinfo)) goto fail; + /* Initialize gst memory with vinfo updated with kms device */ + gst_memory_init (mem, GST_MEMORY_FLAG_NO_SHARE, allocator, NULL, + GST_VIDEO_INFO_SIZE (vinfo), 0, 0, GST_VIDEO_INFO_SIZE (vinfo)); + return mem; /* ERRORS */ @@ -419,6 +433,10 @@ gst_kms_allocator_dmabuf_import (GstAllocator * allocator, gint * prime_fds, if (!gst_kms_allocator_add_fb (alloc, tmp, offsets, vinfo)) goto failed; + /* Initialize gst memory with vinfo updated with kms device */ + gst_memory_init (mem, GST_MEMORY_FLAG_NO_SHARE, allocator, NULL, + GST_VIDEO_INFO_SIZE (vinfo), 0, 0, GST_VIDEO_INFO_SIZE (vinfo)); + return tmp; /* ERRORS */ -- 2.7.4