导航

    全志在线开发者论坛

    • 注册
    • 登录
    • 搜索
    • 版块
    • 话题
    • 在线文档
    • 社区主页

    关于sunxi图层设置DISP_LAYER_SET_CONFIG的一个问题

    其它全志芯片讨论区
    4
    18
    6923
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • L
      laocai LV 5 最后由 laocai 编辑

      通过ioctl函数传递的图层参数,framebuffer地址(即下面的add[0])到底是物理地址还是虚拟地址?这个framebuffer由应用层提供,有没有什么特别要求?比如地址对齐要求、连续内存要求等等。另外哪里能找到说明文档或者参考代码?

      /* 选择图层所需的通道以及本图层参数 */
      config.channel = 0;
      config.layer_id = 0;
      config.info.enable = 1;
      config.info.mode = LAYER_MODE_BUFFER;
      config.info.fb.addr[0] = (unsigned long long)mem_in; //FB物理地址
      config.info.fb.size[0].width = width;
      config.info.fb.size[0].height = height;
      config.info.fb.align[0] = 4; //4bytes align
      config.info.fb.format = DISP_FORMAT_ARGB_8888;
      
      /* 上层调用DE显示引擎所用的ioctl接口 */
      arg[0] = 0; //screen_id 0表示选择通路0
      arg[1] = (unsigned long)&config;
      arg[2] = 1;//表示设置图层数量为1
      ret = ioctl(disphd, DISP_LAYER_SET_CONFIG, (void *)arg);
      
      
      L 2 条回复 最后回复 回复 引用 分享 0
      • L
        laocai LV 5 @laocai 最后由 laocai 编辑

        @laocai
        821933-20221222185942766-1348918999.png

        这是我网上搜到的一张图片,这段代码使用了android的ion库来创建framebuffer。sunxi图层创建必须要用ion库吗?


        PS,这段代码是采用DISP_LAYER_SET_CONFIG2配置,所以是用ion memory,那么DISP_LAYER_SET_CONFIG配置呢,DISP_LAYER_SET_CONFIG配置的时候,应用程序该如何准备图层的framebuffer?有没有大神能解释一下

        xiaowenge 1 条回复 最后回复 回复 引用 分享 0
        • xiaowenge
          DOT小文哥 LV 8 @laocai 最后由 编辑

          @laocai 在 关于sunxi图层设置DISP_LAYER_SET_CONFIG的一个问题 中说:

          @laocai
          网上图片

          网上图片挂了

          L 1 条回复 最后回复 回复 引用 分享 0
          • L
            laocai LV 5 @xiaowenge 最后由 编辑

            @xiaowenge 图片没挂,只是不支持外链。

            1 条回复 最后回复 回复 引用 分享 0
            • L
              laocai LV 5 最后由 编辑

              另外全志的文档中提到sunxi_display2.h,我发现这个头文件不能直接用于应用程序开发。原因是它引用了很多只有内核中才用到的c语言类型,如s32等。请问全志的sunxi应用程序开发到底要使用什么样的开发环境呢?屏幕截图 2023-12-01 174857.png

              Z Z 2 条回复 最后回复 回复 引用 分享 0
              • Z
                zheng1 LV 3 @laocai 最后由 编辑

                @laocai tina的sdk有一个libuapi库是对这部分接口的封装,我在v851s上用DISP_LAYER_SET_CONFIG2会导致内核内存泄漏,你可以试试有没有同样的问题

                L 2 条回复 最后回复 回复 引用 分享 0
                • L
                  laocai LV 5 @zheng1 最后由 编辑

                  @zheng1 之前我只用了tina linux内核,没有安装tina sdk。
                  等我把tina sdk安装了看看,全志要能提供更详细的使用说明就好了。

                  L 4 条回复 最后回复 回复 引用 分享 0
                  • L
                    laocai LV 5 @laocai 最后由 编辑

                    @laocai 找到了libuapi\src\ion_alloc.c中的代码

                    /* return virtual address: 0 failed */
                    void* sunxi_ion_alloc_palloc(int size)
                    {
                        aw_ion_allocation_info_t alloc_data;
                        ion_fd_data_t fd_data;
                        struct ion_handle_data handle_data;
                        struct aw_ion_custom_info custom_data;
                        sunxi_phys_data   phys_data;
                        struct user_iommu_param iommu_param;
                    
                        int rest_size = 0;
                        unsigned long addr_phy = 0;
                        unsigned long addr_vir = 0;
                        buffer_node * alloc_buffer = NULL;
                        int ret = 0;
                        char *cache_flag;
                        pthread_mutex_lock(&g_ion_mutex_alloc);
                    
                        if (g_ion_alloc_context == NULL) {
                    		loge("call ion_alloc_open\n");
                            goto ALLOC_OUT;
                        }
                    
                        if (size <= 0) {
                            loge("can not alloc size 0\n");
                            goto ALLOC_OUT;
                        }
                    
                        memset(&alloc_data, 0, sizeof(alloc_data));
                        memset(&fd_data, 0, sizeof(fd_data));
                    
                        alloc_data.aw_len = (size_t)size;
                        alloc_data.aw_align = ION_ALLOC_ALIGN ;
                    
                    #if defined(CONF_KERNEL_IOMMU)
                        alloc_data.aw_heap_id_mask = AW_ION_SYSTEM_HEAP_MASK | AW_ION_CARVEOUT_HEAP_MASK;
                    #else
                        alloc_data.aw_heap_id_mask = AW_ION_DMA_HEAP_MASK | AW_ION_CARVEOUT_HEAP_MASK;
                    #endif
                        cache_flag = getenv("MG_IONBUFFER");
                        if(cache_flag == NULL || strcmp(cache_flag, "1") != 0){
                            alloc_data.flags = AW_ION_CACHED_FLAG | AW_ION_CACHED_NEEDS_SYNC_FLAG;
                        }
                    
                    #if CONF_KERNEL_VERSION_OLD
                        ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_ALLOC, &alloc_data);
                        if (ret) {
                            loge("ION_IOC_ALLOC error\n");
                            goto ALLOC_OUT;
                        }
                    
                        /* get dmabuf fd */
                        fd_data.handle = alloc_data.handle;
                        ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_MAP, &fd_data);
                        if (ret) {
                            loge("ION_IOC_MAP err, ret %d, dmabuf fd 0x%08x\n",
                    				ret, (unsigned int)fd_data.aw_fd);
                            goto ALLOC_OUT;
                        }
                    #else
                        struct aw_ion_new_alloc_data data = {
                            .len = alloc_data.aw_len,
                            .heap_id_mask = alloc_data.aw_heap_id_mask,
                            .flags = alloc_data.flags,
                        };
                    
                        ret = ioctl(g_ion_alloc_context->fd, AW_ION_IOC_NEW_ALLOC, &data);
                        if (ret < 0) {
                            loge("AW_ION_IOC_NEW_ALLOC error\n");
                            goto ALLOC_OUT;
                        }
                        fd_data.aw_fd = data.fd;
                    #endif
                    
                        /* mmap to user */
                        addr_vir = (unsigned long)mmap(NULL, alloc_data.aw_len, \
                            PROT_READ|PROT_WRITE, MAP_SHARED, fd_data.aw_fd, 0);
                    
                        if ((unsigned long)MAP_FAILED == addr_vir) {
                            loge("mmap err, ret %u\n", (unsigned int)addr_vir);
                            addr_vir = 0;
                            goto ALLOC_OUT;
                        }
                    
                        /* get phy address */
                    #if defined(CONF_KERNEL_IOMMU)
                        memset(&iommu_param, 0, sizeof(iommu_param));
                        iommu_param.fd = fd_data.aw_fd;
                        ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_ENGINE_REQ, 0);
                        if (ret) {
                            loge("ENGINE_REQ err, ret %d\n", ret);
                            addr_phy = 0;
                            addr_vir = 0;
                            goto ALLOC_OUT;
                        }
                        ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_GET_IOMMU_ADDR, &iommu_param);
                        if (ret) {
                            loge("GET_IOMMU_ADDR err, ret %d\n", ret);
                            addr_phy = 0;
                            addr_vir = 0;
                            goto ALLOC_OUT;
                        }
                        addr_phy = iommu_param.iommu_addr;
                    #else
                        memset(&phys_data, 0, sizeof(phys_data));
                        phys_data.handle = alloc_data.handle;
                        phys_data.size = size;
                        custom_data.aw_cmd = ION_IOC_SUNXI_PHYS_ADDR;
                        custom_data.aw_arg = (unsigned long)&phys_data;
                        ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_CUSTOM, &custom_data);
                        if (ret) {
                            loge("ION_IOC_CUSTOM err, ret %d\n", ret);
                            addr_phy = 0;
                            addr_vir = 0;
                            goto ALLOC_OUT;
                        }
                        addr_phy = phys_data.phys_addr;
                    #endif
                    
                        alloc_buffer = (buffer_node *)malloc(sizeof(buffer_node));
                        if (alloc_buffer == NULL) {
                            loge("malloc buffer node failed");
                    
                            /* unmmap */
                            ret = munmap((void*)addr_vir, alloc_data.aw_len);
                            if (ret) {
                                loge("munmap err, ret %d\n", ret);
                            }
                    
                    #if defined(CONF_KERNEL_IOMMU)
                            ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_ENGINE_REL, 0);
                            if (ret)
                                logv("ENGINE_REL failed\n");
                    
                            ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_FREE_IOMMU_ADDR, &iommu_param);
                            if (ret)
                                logv("FREE_IOMMU_ADDR err, ret %d\n", ret);
                    #endif
                    
                            /* close dmabuf fd */
                            close(fd_data.aw_fd);
                    
                            /* free buffer */
                            handle_data.handle = alloc_data.handle;
                            ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_FREE, &handle_data);
                            if(ret)
                                loge("ION_IOC_FREE err, ret %d\n", ret);
                    
                            addr_phy = 0;
                            addr_vir = 0; /* value of MAP_FAILED is -1, should return 0*/
                    
                            goto ALLOC_OUT;
                        }
                        alloc_buffer->phy = addr_phy;
                        alloc_buffer->vir = addr_vir;
                        alloc_buffer->user_virt = addr_vir;
                        alloc_buffer->size = size;
                        alloc_buffer->fd_data.handle = fd_data.handle;
                        alloc_buffer->fd_data.aw_fd = fd_data.aw_fd;
                    
                        aw_mem_list_add_tail(&alloc_buffer->i_list, &g_ion_alloc_context->list);
                    
                    #if DEBUG_ION_REF==1
                        cdx_use_mem += size;
                        int i = 0;
                        for (i = 0; i < ION_BUF_LEN; i++) {
                            if (ion_buf_nodes_test[i].addr == 0
                    				&& ion_buf_nodes_test[i].size == 0) {
                                ion_buf_nodes_test[i].addr = addr_vir;
                                ion_buf_nodes_test[i].size = size;
                                break;
                            }
                        }
                    
                        if (i>= ION_BUF_LEN) {
                            loge("error, ion buf len is large than [%d]", ION_BUF_LEN);
                        }
                    #endif
                    
                    ALLOC_OUT:
                        pthread_mutex_unlock(&g_ion_mutex_alloc);
                        return (void*)addr_vir;
                    }
                    

                    根据配置不同,libuapi使用ion设备或者cedar设备来分配内存。

                    1 条回复 最后回复 回复 引用 分享 0
                    • L
                      laocai LV 5 @laocai 最后由 laocai 编辑

                      @laocai 而选择ion设备还是cedar设备,是由编译选项决定的。如果要采用DISP_LAYER_SET_CONFIG2,必须编译的时候选择SUNXI_ALLOC_IOMMU,不知道我的理解是否正确?我找到的关于全志disp的讨论

                      choice
                      prompt "Choose alloc method"
                      	default SUNXI_ALLOC_CMA
                      	help
                      	Select how to apply for memory.
                      config SUNXI_ALLOC_CMA
                      	bool "sunxi_alloc_cma"
                      config SUNXI_ALLOC_IOMMU
                      	bool "sunxi_alloc_iommu"
                      endchoice
                      choice
                      prompt "Choose layer alloc method"
                      	default LUAPI_LAYER_ALLOC_CHN
                      	help
                      	Select how to apply for layer.
                      config LUAPI_LAYER_ALLOC_CHN
                      	bool "luapi_layer_alloc_chn"
                      config LUAPI_LAYER_ALLOC_LAY
                      	bool "luapi_layer_alloc_lay"
                      endchoice
                      choice
                      prompt "Choose display rendering mode"
                      	default SUNXI_DISPLAY_DE
                      	help
                      		Choose display rendering mode, DE or GPU.
                      config SUNXI_DISPLAY_DE
                      	bool "DE"
                      config SUNXI_DISPLAY_GPU
                      	bool "GPU"
                      	help
                      	Define the macro SUNXI_DISPLAY_GPU, use GPU rendering, send the RGBA data
                      	after rendering to fb1 display, execute export FRAMEBUFFER=/dev/fb1
                      	before executing the program, no longer support DispSetEnable, DispSetSrcRect,
                      	DispSetZorder and DispSetIoctl functions.
                      
                      	Define the macro SUNXI_DISPLAY_GPU and SUNXI_DISPLAY_GPU_BUF, use GPU rendering,
                      	send the RGBA data after rendering to layer. No longer support DispSetSrcRect functions.
                      	Default use.
                      endchoice
                      endif
                      endef
                      
                      define Build/Prepare
                      	$(INSTALL_DIR) $(PKG_BUILD_DIR)/
                      	$(CP) ./src $(PKG_BUILD_DIR)/
                      endef
                      
                      define Build/Configure
                      endef
                      
                      ifeq ($(CONFIG_SUNXI_DISPLAY_TWO),y)
                      TARGET_CFLAGS+=-D__SUNXI_DISPLAY2__
                      TARGET_CFLAGS+=-D$(KERNEL_VERSION)
                      endif
                      ifeq ($(CONFIG_SUNXI_DISPLAY_ONE),y)
                      TARGET_CFLAGS+=-D__SUNXI_DISPLAY__
                      TARGET_CFLAGS+=-D$(KERNEL_VERSION)
                      endif
                      
                      ifeq ($(CONFIG_SUNXI_ALLOC_CMA),y)
                      TARGET_CFLAGS+=-DCONF_KERNEL_CMA
                      endif
                      ifeq ($(CONFIG_SUNXI_ALLOC_IOMMU),y)
                      TARGET_CFLAGS+=-DCONF_KERNEL_IOMMU
                      endif
                      

                      另外我还发现,linux 内核5.4版本的时候,libuapi库无法使用ion设备来分配framebuffer,原因就是代码里面根本没有实现alloc_data的赋值。

                      #if CONF_KERNEL_VERSION_OLD
                          ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_ALLOC, &alloc_data);
                          if (ret) {
                              loge("ION_IOC_ALLOC error\n");
                              goto ALLOC_OUT;
                          }
                      
                          /* get dmabuf fd */
                          fd_data.handle = alloc_data.handle;
                          ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_MAP, &fd_data);
                          if (ret) {
                              loge("ION_IOC_MAP err, ret %d, dmabuf fd 0x%08x\n",
                      				ret, (unsigned int)fd_data.aw_fd);
                              goto ALLOC_OUT;
                          }
                      #else
                          struct aw_ion_new_alloc_data data = {
                              .len = alloc_data.aw_len,
                              .heap_id_mask = alloc_data.aw_heap_id_mask,
                              .flags = alloc_data.flags,
                          };
                      
                          ret = ioctl(g_ion_alloc_context->fd, AW_ION_IOC_NEW_ALLOC, &data);
                          if (ret < 0) {
                              loge("AW_ION_IOC_NEW_ALLOC error\n");
                              goto ALLOC_OUT;
                          }
                          fd_data.aw_fd = data.fd;
                      #endif
                      
                          /* get phy address */
                      #if defined(CONF_KERNEL_IOMMU)
                          memset(&iommu_param, 0, sizeof(iommu_param));
                          iommu_param.fd = fd_data.aw_fd;
                          ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_ENGINE_REQ, 0);
                          if (ret) {
                              loge("ENGINE_REQ err, ret %d\n", ret);
                              addr_phy = 0;
                              addr_vir = 0;
                              goto ALLOC_OUT;
                          }
                          ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_GET_IOMMU_ADDR, &iommu_param);
                          if (ret) {
                              loge("GET_IOMMU_ADDR err, ret %d\n", ret);
                              addr_phy = 0;
                              addr_vir = 0;
                              goto ALLOC_OUT;
                          }
                          addr_phy = iommu_param.iommu_addr;
                      #else
                          memset(&phys_data, 0, sizeof(phys_data));
                          phys_data.handle = alloc_data.handle;
                          phys_data.size = size;
                          custom_data.aw_cmd = ION_IOC_SUNXI_PHYS_ADDR;
                          custom_data.aw_arg = (unsigned long)&phys_data;
                          ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_CUSTOM, &custom_data);
                          if (ret) {
                              loge("ION_IOC_CUSTOM err, ret %d\n", ret);
                              addr_phy = 0;
                              addr_vir = 0;
                              goto ALLOC_OUT;
                          }
                          addr_phy = phys_data.phys_addr;
                      #endif
                      
                      1 条回复 最后回复 回复 引用 分享 0
                      • L
                        laocai LV 5 @laocai 最后由 编辑

                        @laocai 我找到了一个简单使用libuapi库的例子,在tina-package/blob/main/gui/littlevgl-8/lv_drivers/display/sunximem.c

                        /**
                         * @file sunximem.c
                         *
                         */
                        
                        /*********************
                         *      INCLUDES
                         *********************/
                        #include "sunximem.h"
                        
                        #if USE_SUNXIFB_G2D
                        
                        #include <stdio.h>
                        #include <ion_mem_alloc.h>
                        
                        /*********************
                         *      DEFINES
                         *********************/
                        
                        /**********************
                         *      TYPEDEFS
                         **********************/
                        
                        /**********************
                         *      STRUCTURES
                         **********************/
                        
                        /**********************
                         *  STATIC PROTOTYPES
                         **********************/
                        static struct SunxiMemOpsS *memops;
                        
                        /**********************
                         *  STATIC VARIABLES
                         **********************/
                        
                        /**********************
                         *      MACROS
                         **********************/
                        
                        /**********************
                         *   GLOBAL FUNCTIONS
                         **********************/
                        
                        bool sunxifb_mem_init() {
                            if (memops)
                                return true;
                        
                            memops = GetMemAdapterOpsS();
                            if (SunxiMemOpen(memops) < 0) {
                                perror("Error: cannot open ion device");
                                return false;
                            }
                        
                            return true;
                        }
                        
                        void sunxifb_mem_deinit() {
                            if (memops) {
                                SunxiMemClose(memops);
                                memops = NULL;
                            }
                        }
                        
                        void* sunxifb_mem_alloc(size_t size, char *label) {
                            if (size == 0) {
                                printf("size illegal.");
                                return NULL;
                            }
                        
                            void *alloc = SunxiMemPalloc(memops, size);
                            if (alloc == NULL) {
                                printf("couldn't allocate memory (%lu bytes).", (unsigned long) size);
                                return NULL;
                            }
                        
                        #ifdef LV_USE_SUNXIFB_DEBUG
                            printf("%s: sunxifb_mem_alloc=%p size=%lu bytes\n", label, alloc, (unsigned long) size);
                        #endif /* LV_USE_SUNXIFB_DEBUG */
                        
                            return alloc;
                        }
                        
                        void sunxifb_mem_free(void **data, char *label) {
                            if (*data != NULL) {
                        #ifdef LV_USE_SUNXIFB_DEBUG
                                printf("%s: sunxifb_mem_free=%p\n", label, *data);
                        #endif /* LV_USE_SUNXIFB_DEBUG */
                                SunxiMemPfree(memops, *data);
                                *data = NULL;
                            } else {
                                printf("couldn't free memory.\n");
                            }
                        }
                        
                        void* sunxifb_mem_get_phyaddr(void *data) {
                            if (data != NULL)
                                return SunxiMemGetPhysicAddressCpu(memops, data);
                            else
                                return NULL;
                        }
                        
                        void sunxifb_mem_flush_cache(void *data, size_t size) {
                            SunxiMemFlushCache(memops, data, size);
                        }
                        
                        /**********************
                         *   STATIC FUNCTIONS
                         **********************/
                        
                        #endif
                        
                        1 条回复 最后回复 回复 引用 分享 0
                        • L
                          laocai LV 5 @laocai 最后由 编辑

                          @laocai 如果要获得framebuffer的物理地址,就采用这个方法

                          void* sunxifb_mem_get_phyaddr(void *data) {
                              if (data != NULL)
                                  return SunxiMemGetPhysicAddressCpu(memops, data);
                              else
                                  return NULL;
                          }
                          
                          L 1 条回复 最后回复 回复 引用 分享 0
                          • L
                            laocai LV 5 @laocai 最后由 laocai 编辑

                            @laocai 另外关于sunxi_display2.h文件,我在tina sdk的package中发现了七个路径下有这个文件,前面三个文件的内容各不相同,和内核使用的sunxi_display2.h文件也不同。
                            allwinner/libAWIspApi/src/isp522/libisp/include/device/sunxi_display2.h
                            allwinner/tina_multimedia/libcedarx/demo/xplayerdemo/sunxi_display2.h
                            allwinner/tina_multimedia/libcedarx/demo/recoderdemo/sunxi_display2.h
                            allwinner/libuapi/src/sunxi_display_v2.h
                            testtools/tinatest/testcase/base/production/displaytester/common/sunxi_display_v2.h
                            allwinner/tinacvr/src/middle_ware/sunxi_display_v2.h
                            gui/minigui/multimedia-test/src/middle_ware/sunxi_display_v2.h

                            比较了一下,和内核头文件最接近的是allwinner/libAWIspApi/src/isp522/libisp/include/device/sunxi_display2.h
                            cmp.jpg

                            allwinner/tinacvr/src/middle_ware/sunxi_display_v2.h和allwinner/libuapi/src/sunxi_display_v2.h比较接近,后者像是在前者基础上修改而来。

                            1 条回复 最后回复 回复 引用 分享 0
                            • L
                              laocai LV 5 @zheng1 最后由 编辑

                              @zheng1 在 关于sunxi图层设置DISP_LAYER_SET_CONFIG的一个问题 中说:

                              @laocai tina的sdk有一个libuapi库是对这部分接口的封装,我在v851s上用DISP_LAYER_SET_CONFIG2会导致内核内存泄漏,你可以试试有没有同样的问题

                              我猜你遇到的问题可能和这段代码有关:

                              #if defined(CONF_KERNEL_IOMMU)
                                          ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_ENGINE_REL, 0);
                                          if (ret)
                                              logv("ENGINE_REL failed\n");
                              
                                          struct user_iommu_param iommu_param;
                                          memset(&iommu_param, 0, sizeof(iommu_param));
                                          iommu_param.fd = tmp->fd_data.aw_fd;
                                          ret = ioctl(g_ion_alloc_context->cedar_fd, AW_MEM_FREE_IOMMU_ADDR, &iommu_param);
                                          if (ret)
                                              logv("FREE_IOMMU_ADDR err, ret %d\n", ret);
                              #endif
                              
                                          /*close dma buffer fd*/
                                          close(tmp->fd_data.aw_fd);
                                          /* free buffer */
                                          handle_data.handle = tmp->fd_data.handle;
                              
                                          ret = ioctl(g_ion_alloc_context->fd, AW_MEM_ION_IOC_FREE, &handle_data);
                                          if (ret)
                                              logv("TON_IOC_FREE failed\n");
                              
                                          aw_mem_list_del(&tmp->i_list);
                                          free(tmp);
                              
                                          flag = 1;
                              
                                      handle_data.handle = tmp->fd_data.handle;
                              

                              内核版本为高版本(5.4)的时候,libuapi库在申请内存时根本没有初始化这个handle。然后释放内存的时候,却又用这个空的handle去调用释放的系统调用,内存根本不可能真正释放。换句话说,这个libuapi库只有在低版本内核上才有可能正常工作;高版本内核上,内存只能申请,无法释放。

                              1 条回复 最后回复 回复 引用 分享 1
                              • L
                                laocai LV 5 @laocai 最后由 编辑

                                @laocai 官方文档里也到处都是错误。
                                ttt.jpg

                                红线处正确的代码应该是这样的:

                                        memset(&config, 0, sizeof(struct disp_layer_config));
                                        config.channel = 0;//blending channel
                                        config.layer_id = 0;//layer index in the blending channel
                                        config.enable = 1;
                                        config.info.mode = LAYER_MODE_BUFFER;
                                
                                Z 1 条回复 最后回复 回复 引用 分享 0
                                • Z
                                  zxdplay LV 4 @laocai 最后由 编辑

                                  @laocai 文档上的源代码根本就没编译验证过

                                  1 条回复 最后回复 回复 引用 分享 0
                                  • Z
                                    zxdplay LV 4 @laocai 最后由 编辑

                                    @laocai 直接把头文件sunxi_display2.h 拷贝出来,然后把编译不过的地方改了,不用的删除掉,像s32就是 signed int , u32 就是 unsgined int

                                    L 1 条回复 最后回复 回复 引用 分享 0
                                    • L
                                      laocai LV 5 @zxdplay 最后由 编辑

                                      @zxdplay 谢谢回复,我后来就是这么做的,形成了一个自己专有的头文件。

                                      L 1 条回复 最后回复 回复 引用 分享 0
                                      • L
                                        laocai LV 5 @laocai 最后由 编辑

                                        @laocai 为什么今天发帖,都是显示forbidden?

                                        1 条回复 最后回复 回复 引用 分享 0
                                        • 1 / 1
                                        • First post
                                          Last post

                                        Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号

                                        行为准则 | 用户协议 | 隐私权政策