This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM5728: memcpy from dmabuf is slow

Part Number: AM5728


eglCreateImageKHR(disp_wl->egl.dpy, EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR, disp_wl->gbm.bo,&attrib_list);

bind fbo.

rendering ...

memcpy data from dmabuf is slow. 

https://e2e.ti.com/support/processors/f/791/t/491377

"This has been taken care in PSDK 3.2 using CMEM buffers. The CMEM driver already had support for cached buffers and now they are enhanced to support dambuf export feature. So for scenarios where CPU need to access buffers, we recommend those buffers to be allocated using CMEM and then exported to the drivers with which they need to be shared. Example can be found in dual camera demo example source code in PSDK."

using cmem alloc buffer, export as dmabuf.

gbm_bo_import the dmabuf return error:

PVR:(Error): [ 7919-> 7921] < gbm_pvr_bo_create_common():217|ERROR> condition [ bo_attrs->opt.import_dmabuf.stride != 0] failed [0, ]
ERROR:create_texture:1440: gbm_bo_import failed

ti-processor-sdk-linux-am57xx-evm-05.02.00.10

code:

case FOURCC('A','R','2','4'):
buf->nbo = 1;
#if 0
buf->bo[0] = alloc_bo(disp, 32, buf->width, buf->height,
&bo_handles[0], &buf->pitches[0]);
#else
//Allocate buffer from CMEM and get the buffer descriptor
buf->fd[0] = alloc_cmem_buffer(buf->width*buf->height*32, 1, &buf->cmem_buf);
if(buf->fd[0] < 0){
free_cmem_buffer(buf->cmem_buf);
printf(" Cannot export CMEM buffer\n");
return NULL;
}

/* Get the omap bo from the fd allocted using CMEM */
buf->bo[0] = omap_bo_from_dmabuf(disp->dev, buf->fd[0]);
bo_handles[0] = omap_bo_handle(buf->bo[0]);
#endif

int dfd = buf->fd[0];
struct gbm_import_fd_data gbm_dmabuf = {
.fd = dfd,
.width = buf->width,
.height = buf->height,
.stride = buf->pitches[0],
.format = GBM_FORMAT_ARGB8888
};

disp_wl->gbm.bo = gbm_bo_import(disp_wl->gbm.dev, GBM_BO_IMPORT_FD, &gbm_dmabuf,

GBM_BO_USE_RENDERING|GBM_BO_USE_SCANOUT);
if(!disp_wl->gbm.bo){
ERROR("gbm_bo_import failed\n");
return -1;
}

EGLint attrib_list = EGL_NONE;
buf_wl->egl_img = disp_wl->egl.eglCreateImageKHR(
disp_wl->egl.dpy,
EGL_NO_CONTEXT,
EGL_NATIVE_PIXMAP_KHR,
disp_wl->gbm.bo,
&attrib_list);

  • Hello,

    You could find example where the buffers are allocated from CMEM pool here:
    software-dl.ti.com/.../Examples_and_Demos_Application_Demos.html
    The source code is allocated here:
    ti-processor-sdk-linux-am57xx-evm-05.02.00.10/example-applications/dual-camera-demo-1.0

    BR
    Margarita
  • yes. cmem buf alloc code is copy from dual-camera-demo.

    attached is the patch to dmabuftest for argb texture.

    root@am57xx-evm:~# ./dmabuftest --kmscube --connector 35 -d /dev/video1 -c 1280x720@NV12

    ...

    CMEM buffer pointer is 0xb2147000
    PVR:(Error): [ 8660-> 8661] < gbm_pvr_bo_create_common():217|ERROR> condition [ bo_attrs->opt.import_dmabuf.stride != 0] failed [0, ]
    ERROR:create_texture:1232: gbm_bo_import failed

    diff -ur omapdrmtest/Makefile omapdrmtest.fbo/Makefile
    --- omapdrmtest/Makefile	2019-03-25 20:38:48.951233612 +0800
    +++ omapdrmtest.fbo/Makefile	2019-03-25 20:14:28.368984221 +0800
    @@ -353,7 +353,7 @@
     INSTALL_SCRIPT = ${INSTALL}
     INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
     LD = /media/y/7b0dae3b-6eb2-40a5-814a-23b19833a4a1/ti-processor-sdk-linux-am57xx-evm-05.02.00.10/linux-devkit/sysroots/x86_64-arago-linux/usr/arm-linux-gnueabihf/bin/ld
    -LDFLAGS = -lm -lavcodec -lpthread
    +LDFLAGS = -lticmem -lm -lavcodec -lpthread
     LIBOBJS = 
     LIBS = 
     LIBTOOL = $(SHELL) $(top_builddir)/libtool
    diff -ur omapdrmtest/util/display-kmscube.c omapdrmtest.fbo/util/display-kmscube.c
    --- omapdrmtest/util/display-kmscube.c	2019-03-25 20:37:45.285014307 +0800
    +++ omapdrmtest.fbo/util/display-kmscube.c	2019-03-25 21:09:28.823936500 +0800
    @@ -77,6 +77,53 @@
     #include <pthread.h>
     
     #include "esUtil.h"
    +#include <ti/cmem.h>
    +#include <linux/dma-buf.h>
    +#include <sys/ioctl.h>
    +
    +#define CMEM_BLOCKID CMEM_CMABLOCKID
    +
    +CMEM_AllocParams cmem_alloc_params = {
    +	CMEM_HEAP,	/* type */
    +	CMEM_CACHED,	/* flags */
    +	1		/* alignment */
    +};
    +
    +void init_cmem()
    +{
    +	CMEM_init();
    +}
    +
    +int alloc_cmem_buffer(unsigned int size, unsigned int align, void **cmem_buf)
    +{
    +	cmem_alloc_params.alignment = align;
    +
    +	*cmem_buf = CMEM_alloc2(CMEM_BLOCKID, size,
    +		&cmem_alloc_params);
    +
    +	if(*cmem_buf == NULL){
    +		printf("CMEM allocation failed");
    +		return -1;
    +	}
    +	printf("CMEM buffer pointer is 0x%x\n",(uint32_t) *cmem_buf );
    +	return CMEM_export_dmabuf(*cmem_buf);
    +}
    +
    +void free_cmem_buffer(void *cmem_buffer)
    +{
    +	CMEM_free(cmem_buffer, &cmem_alloc_params);
    +}
    +
    +int dma_buf_do_cache_operation(int dma_buf_fd, uint32_t cache_operation) 
    +{
    +	int ret;
    +	struct dma_buf_sync sync;
    +	sync.flags = cache_operation;
    +
    +	ret = ioctl(dma_buf_fd, DMA_BUF_IOCTL_SYNC, &sync);
    +
    +	return ret;
    +}
     
     #define MAX_FACES 6
     
    @@ -268,11 +315,15 @@
     	return 0;
     }
     
    +static struct buffer * alloc_buffer(struct display *disp, uint32_t fourcc, uint32_t w, uint32_t h);
    +static struct buffer *fbo_buffer = NULL;
    +static int fbo_texId;
     static int init_gl(struct display_kmscube *disp_kmsc)
     {
     	EGLint major, minor, n;
     	GLuint vertex_shader, fragment_shader;
     	GLint ret;
    +	struct buffer_kmscube *buf_kmsc;
     
     	static const EGLint context_attribs[] = {
     		EGL_CONTEXT_CLIENT_VERSION, 2,
    @@ -397,6 +448,13 @@
     		return -1;
     	}
     
    +	fbo_buffer = alloc_buffer(&disp_kmsc->base, FOURCC_STR("AR24"), 640, 720);
    +	buf_kmsc = to_buffer_kmscube(fbo_buffer);
    +	create_texture(disp_kmsc, fbo_buffer);
    +	fbo_texId = buf_kmsc->texture_name;
    +	fprintf(stderr,"fbo_buffer = %x, fbo_texId = %x fbo_addr = %x\n",fbo_buffer,fbo_texId,fbo_buffer->cmem_buf);
    +	
    +
     	vertex_shader = glCreateShader(GL_VERTEX_SHADER);
     
     	glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
    @@ -804,14 +862,29 @@
     
     	switch(fourcc) {
     	case FOURCC('A','R','2','4'):
    -		buf->nbo = 1;
    +#if 0 
     		buf->bo[0] = alloc_bo(disp, 32, buf->width, buf->height,
     				&bo_handles[0], &buf->pitches[0]);
    +                buf->fd[0] = omap_bo_dmabuf(buf->bo[0]);
    +#else
    +		//Allocate buffer from CMEM and get the buffer descriptor
    +		buf->fd[0]  = alloc_cmem_buffer(buf->width*buf->height*32, 1, &buf->cmem_buf);
    +		if(buf->fd[0] < 0){
    +			free_cmem_buffer(buf->cmem_buf);
    +			printf(" Cannot export CMEM buffer\n");
    +			return NULL;
    +		}
    +
    +		/* Get the omap bo from the fd allocted using CMEM */
    +		buf->bo[0] = omap_bo_from_dmabuf(disp->dev, buf->fd[0]);
    +		bo_handles[0] = omap_bo_handle(buf->bo[0]);
    +#endif
     		break;
     	case FOURCC('R','G','2','4'):
     		buf->nbo = 1;
     		buf->bo[0] = alloc_bo(disp, 24, buf->width, buf->height,
     				&bo_handles[0], &buf->pitches[0]);
    +                buf->fd[0] = omap_bo_dmabuf(buf->bo[0]);
     		break;
     
     	case FOURCC('U','Y','V','Y'):
    @@ -819,6 +892,7 @@
     		buf->nbo = 1;
     		buf->bo[0] = alloc_bo(disp, 16, buf->width, buf->height,
     				&bo_handles[0], &buf->pitches[0]);
    +                buf->fd[0] = omap_bo_dmabuf(buf->bo[0]);
     		break;
     	case FOURCC('N','V','1','2'):
                     if (disp->multiplanar) {
    @@ -844,6 +918,7 @@
     		buf->nbo = 1;
     		buf->bo[0] = alloc_bo(disp, 8, buf->width, (buf->height + buf->height/2),
     				&bo_handles[0], &buf->pitches[0]);
    +                buf->fd[0] = omap_bo_dmabuf(buf->bo[0]);
     		break;
     	default:
     		ERROR("invalid format: 0x%08x", fourcc);
    @@ -1093,7 +1168,8 @@
     	// TODO: cropping attributes when this will be supported.
     	EGLint attr[20];
     	bool isRGB;
    -	int dfd = omap_bo_dmabuf(buf->bo[0]);
    +	//int dfd = omap_bo_dmabuf(buf->bo[0]);
    +	int dfd = buf->fd[0];
     	struct gbm_import_fd_data gbm_dmabuf = {
     		.fd     = dfd,
     		.width  = buf->width,
    @@ -1289,6 +1365,7 @@
     		goto fail;
     	}
     
    +	init_cmem();
     	disp->get_buffers = get_buffers;
     	disp->get_vid_buffers = get_vid_buffers;
     	disp->post_buffer = post_buffer;
    diff -ur omapdrmtest/util/util.h omapdrmtest.fbo/util/util.h
    --- omapdrmtest/util/util.h	2019-03-25 20:35:30.912001817 +0800
    +++ omapdrmtest.fbo/util/util.h	2019-03-25 20:25:06.110157762 +0800
    @@ -59,6 +59,7 @@
     	bool multiplanar;	/* True when Y and U/V are in separate buffers. */
     	int fd[4];		/* dmabuf */
     	bool noScale;
    +	void *cmem_buf;
     };
     

  • Hello,

    From the error, it seems like stride[] is zero. Please check if stride is set.

    BR
    Margarita

  • Many .so no source code available,I can't find where to change the stride.

  • Hello,

    Please print the stride in your application and confirm it is not 0.

    BR
    Margarita
  • No struct info where the ->stride is ?

  • Hello,

    yang camel said:

    case FOURCC('A','R','2','4'):
    buf->nbo = 1;
    #if 0
    buf->bo[0] = alloc_bo(disp, 32, buf->width, buf->height,
    &bo_handles[0], &buf->pitches[0]);
    #else
    //Allocate buffer from CMEM and get the buffer descriptor
    buf->fd[0] = alloc_cmem_buffer(buf->width*buf->height*32, 1, &buf->cmem_buf);
    if(buf->fd[0] < 0){
    free_cmem_buffer(buf->cmem_buf);
    printf(" Cannot export CMEM buffer\n");
    return NULL;
    }

    /* Get the omap bo from the fd allocted using CMEM */
    buf->bo[0] = omap_bo_from_dmabuf(disp->dev, buf->fd[0]);
    bo_handles[0] = omap_bo_handle(buf->bo[0]);
    #endif

    int dfd = buf->fd[0];
    struct gbm_import_fd_data gbm_dmabuf = {
    .fd = dfd,
    .width = buf->width,
    .height = buf->height,
    .stride = buf->pitches[0],
    .format = GBM_FORMAT_ARGB8888
    };

    disp_wl->gbm.bo = gbm_bo_import(disp_wl->gbm.dev, GBM_BO_IMPORT_FD, &gbm_dmabuf,

    GBM_BO_USE_RENDERING|GBM_BO_USE_SCANOUT);
    if(!disp_wl->gbm.bo){
    ERROR("gbm_bo_import failed\n");
    return -1;
    }

    EGLint attrib_list = EGL_NONE;
    buf_wl->egl_img = disp_wl->egl.eglCreateImageKHR(
    disp_wl->egl.dpy,
    EGL_NO_CONTEXT,
    EGL_NATIVE_PIXMAP_KHR,
    disp_wl->gbm.bo,
    &attrib_list);

    BR
    Margarita