• 8.4.1 MainPage显存管理即页面框架


    1.页面的框架

    main_page.c

    #include <config.h>
    #include <page_manager.h>
    
    static T_PageAction g_tMainPageAction = {
    	.name          = "main",
    	.Run           = MainPageRun,
    	.GetInputEvent = MainPageGetInputEvent,
    	.Prepare       = MainPagePrepare;
    };
    
    static void MainPageRun(void)
    {
    	/* 1. 显示页面 */
        ShowMainPage(g_atMainPageLayOut);
    
    	/* 2. 创建Prepare线程 */
    
    	/* 3. 调用GetInputEvent获得输入事件,进而处理 */
    	while (1)
    	{
    		InputEvent = MainPageGetInputEvent();
    		switch (InputEvent)	
    		{
    			case "浏览模式":
    			{
    				/* 保存当前页面 */
    				StorePage();
    				
    				Page("explore")->Run();
    				
    				/* 恢复之前的页面 */
    				RestorePage();
    				break;
    			}
    			case "连播模式":
    			{
    				/* 保存当前页面 */
    				StorePage();
    
    				Page("auto")->Run();
    				break;
    			}
    			case "设置":
    			{
    				/* 保存当前页面 */
    				StorePage();
    				Page("setting")->Run();
    				/* 恢复之前的页面 */
    				RestorePage();
    				break;
    			}		
    		}
    	}
    }
    
    
    int MainPageGetInputEvent(...)
    {
    	/* 获得原始的触摸屏数据 
    	* 它是调用input_manager.c的函数,此函数会让当前线否休眠
    	* 当触摸屏线程获得数据后,会把它唤醒
    	*/
    	GetInputEvent();
    	
    	/* 处理数据 */
    }
    
    int MainPageInit(void)
    {
    	return RegisterPageAction(&g_tMainPageAction);
    }
    

    2.显存管理

    3.函数解析

    头文件中的结构体

    disp_manager.h

    /* 显示区域,含该区域的左上角/右下角座标
    * 如果是图标,还含有图标的文件名
    */
    typedef struct Layout {
    	int iTopLeftX;
    	int iTopLeftY;
    	int iBotRightX;
    	int iBotRightY;
    	char *strIconName;
    }T_Layout, *PT_Layout;
    
    
    /* VideoMem的状态:
    * 空闲/用于预先准备显示内容/用于当前线程
    */
    typedef enum {
    	VMS_FREE = 0,
    	VMS_USED_FOR_PREPARE,
    	VMS_USED_FOR_CUR,	
    }E_VideoMemState;
    
    /* VideoMem中内存里图片的状态:
    * 空白/正在生成/已经生成
    */
    typedef enum {
    	PS_BLANK = 0,
    	PS_GENERATING,
    	PS_GENERATED,	
    }E_PicState;
    
    
    typedef struct VideoMem {
    	int iID;                        /* ID值,用于标识不同的页面 */
    	int bDevFrameBuffer;            /* 1: 这个VideoMem是显示设备的显存; 0: 只是一个普通缓存 */
    	E_VideoMemState eVideoMemState; /* 这个VideoMem的状态 */
    	E_PicState ePicState;           /* VideoMem中内存里图片的状态 */
    	T_PixelDatas tPixelDatas;       /* 内存: 用来存储图像 */
    	struct VideoMem *ptNext;        /* 链表 */
    }T_VideoMem, *PT_VideoMem;
    

    disp_manager.c

    AllocVideoMem

    int AllocVideoMem(int iNum)
    {
    	int i;
    
    	int iXres = 0;
    	int iYres = 0;
    	int iBpp  = 0;
    
    	int iVMSize;
    	int iLineBytes;
    
    	PT_VideoMem ptNew;
    
    	/* 确定VideoMem的大小
    	*/
    	GetDispResolution(&iXres, &iYres, &iBpp);
    	iVMSize = iXres * iYres * iBpp / 8;
    	iLineBytes = iXres * iBpp / 8;
    
    	/* 先把设备本身的framebuffer放入链表
    	* 分配一个T_VideoMem结构体, 注意我们没有分配里面的tPixelDatas.aucPixelDatas
    	* 而是让tPixelDatas.aucPixelDatas指向显示设备的framebuffer
    	*/
    	ptNew = malloc(sizeof(T_VideoMem));
    	if (ptNew == NULL)
    	{
    		return -1;
    	}
    
    	/* 指向framebuffer */
    	ptNew->tPixelDatas.aucPixelDatas = g_ptDefaultDispOpr->pucDispMem;
    	
    	ptNew->iID = 0;
    	ptNew->bDevFrameBuffer = 1;        /* 表示这个VideoMem是设备本身的framebuffer, 而不是用作缓存作用的VideoMem */
    	ptNew->eVideoMemState  = VMS_FREE;
    	ptNew->ePicState	   = PS_BLANK;
    	ptNew->tPixelDatas.iWidth  = iXres;
    	ptNew->tPixelDatas.iHeight = iYres;
    	ptNew->tPixelDatas.iBpp    = iBpp;
    	ptNew->tPixelDatas.iLineBytes  = iLineBytes;
    	ptNew->tPixelDatas.iTotalBytes = iVMSize;
    
    	if (iNum != 0)
    	{
    		/* 如果下面要分配用于缓存的VideoMem, 
    		* 把设备本身framebuffer对应的VideoMem状态设置为VMS_USED_FOR_CUR,
    		* 表示这个VideoMem不会被作为缓存分配出去
    		*/
    		ptNew->eVideoMemState = VMS_USED_FOR_CUR;
    	}
    	
    	/* 放入链表 */
    	ptNew->ptNext = g_ptVideoMemHead;
    	g_ptVideoMemHead = ptNew;
    	
    
    	/*
    	* 分配用于缓存的VideoMem
    	*/
    	for (i = 0; i < iNum; i++)
    	{
    		/* 分配T_VideoMem结构体本身和"跟framebuffer同样大小的缓存" */
    		/* 这里分配的sizeof(T_VideoMem) + iVMSize即一个文件头,和剩下的framebuffer大小的内存空间
    		 */
    		ptNew = malloc(sizeof(T_VideoMem) + iVMSize);
    		if (ptNew == NULL)
    		{
    			return -1;
    		}
    		/* 在T_VideoMem结构体里记录上面分配的"跟framebuffer同样大小的缓存" */
    		ptNew->tPixelDatas.aucPixelDatas = (unsigned char *)(ptNew + 1);
    
    		ptNew->iID = 0;
    		ptNew->bDevFrameBuffer = 0;
    		ptNew->eVideoMemState = VMS_FREE;
    		ptNew->ePicState      = PS_BLANK;
    		ptNew->tPixelDatas.iWidth  = iXres;
    		ptNew->tPixelDatas.iHeight = iYres;
    		ptNew->tPixelDatas.iBpp    = iBpp;
    		ptNew->tPixelDatas.iLineBytes = iLineBytes;
    		ptNew->tPixelDatas.iTotalBytes = iVMSize;
    
    		/* 放入链表 */
    		ptNew->ptNext = g_ptVideoMemHead;
    		g_ptVideoMemHead = ptNew;
    	}
    	
    	return 0;
    }
    

    GetVideoMem

    /**********************************************************************
     * 函数名称: GetVideoMem
     * 功能描述: 获得一块可操作的VideoMem(它用于存储要显示的数据), 
     *            用完后用PutVideoMem来释放
     * 输入参数: iID  - ID值,先尝试在众多VideoMem中找到ID值相同的
     *            bCur - 1表示当前程序马上要使用VideoMem,无法如何都要返回一个VideoMem
     *                   0表示这是为了改进性能而提前取得VideoMem,不是必需的
     * 输出参数: 无
     * 返 回 值: NULL   - 失败,没有可用的VideoMem
     *            非NULL - 成功,返回PT_VideoMem结构体
     * 修改日期        版本号     修改人	      修改内容
     * -----------------------------------------------
     * 2013/02/08	     V1.0	  韦东山	      创建
     ***********************************************************************/
    PT_VideoMem GetVideoMem(int iID, int bCur)
    {
    	PT_VideoMem ptTmp = g_ptVideoMemHead;
    	
    	/* 1. 优先: 取出空闲的、ID相同的videomem */
    	while (ptTmp)
    	{
    		if ((ptTmp->eVideoMemState == VMS_FREE) && (ptTmp->iID == iID))
    		{
    			ptTmp->eVideoMemState = bCur ? VMS_USED_FOR_CUR : VMS_USED_FOR_PREPARE;
    			return ptTmp;
    		}
    		ptTmp = ptTmp->ptNext;
    	}
    
    	/* 2. 如果前面不成功, 取出一个空闲的并且里面没有数据(ptVideoMem->ePicState = PS_BLANK)的VideoMem */
    	ptTmp = g_ptVideoMemHead;
    	while (ptTmp)
    	{
    		if ((ptTmp->eVideoMemState == VMS_FREE) && (ptTmp->ePicState == PS_BLANK))
    		{
    			ptTmp->iID = iID;
    			ptTmp->eVideoMemState = bCur ? VMS_USED_FOR_CUR : VMS_USED_FOR_PREPARE;
    			return ptTmp;
    		}
    		ptTmp = ptTmp->ptNext;
    	}	
    	
    	/* 3. 如果前面不成功: 取出任意一个空闲的VideoMem */
    	ptTmp = g_ptVideoMemHead;
    	while (ptTmp)
    	{
    		if (ptTmp->eVideoMemState == VMS_FREE)
    		{
    			ptTmp->iID = iID;
    			ptTmp->ePicState = PS_BLANK;
    			ptTmp->eVideoMemState = bCur ? VMS_USED_FOR_CUR : VMS_USED_FOR_PREPARE;
    			return ptTmp;
    		}
    		ptTmp = ptTmp->ptNext;
    	}
    
    	/* 4. 如果没有空闲的VideoMem并且bCur为1, 则取出任意一个VideoMem(不管它是否空闲) */
    	if (bCur)
    	{
    		ptTmp = g_ptVideoMemHead;
    		ptTmp->iID = iID;
    		ptTmp->ePicState = PS_BLANK;
    		ptTmp->eVideoMemState = bCur ? VMS_USED_FOR_CUR : VMS_USED_FOR_PREPARE;
    		return ptTmp;
    	}
    	
    	return NULL;
    }
    

    PutVideoMem

    /**********************************************************************
     * 函数名称: PutVideoMem
     * 功能描述: 使用GetVideoMem获得的VideoMem, 用完时用PutVideoMem释放掉
     * 输入参数: ptVideoMem - 使用完毕的VideoMem
     * 输出参数: 无
     * 返 回 值: 无
     * 修改日期        版本号     修改人	      修改内容
     * -----------------------------------------------
     * 2013/02/08	     V1.0	  韦东山	      创建
     ***********************************************************************/
    void PutVideoMem(PT_VideoMem ptVideoMem)
    {
    	ptVideoMem->eVideoMemState = VMS_FREE;  /* 设置VideoMem状态为空闲 */
    	if (ptVideoMem->iID == -1)
    	{
    		ptVideoMem->ePicState = PS_BLANK;  /* 表示里面的数据没有用了 */
    	}
    }
    

    render.c

    FlushVideoMemToDev

    /**********************************************************************
     * 函数名称: FlushVideoMemToDev
     * 功能描述: 把缓冲区中的数据刷到显示设备上去,即在显示设备上显示缓冲区中的图像
     * 输入参数: ptVideoMem - 缓冲区,内含象素数据
     * 输出参数: 无
     * 返 回 值: 0 - 成功, 其他值 - 失败
     * 修改日期        版本号     修改人	      修改内容
     * -----------------------------------------------
     * 2013/02/08	     V1.0	  韦东山	      创建
     ***********************************************************************/
    void FlushVideoMemToDev(PT_VideoMem ptVideoMem)
    {
    	//memcpy(GetDefaultDispDev()->pucDispMem, ptVideoMem->tPixelDatas.aucPixelDatas, ptVideoMem.tPixelDatas.iHeight * ptVideoMem.tPixelDatas.iLineBytes);
    	if (!ptVideoMem->bDevFrameBuffer)
    	{
    		GetDefaultDispDev()->ShowPage(ptVideoMem);
    	}
    }
  • 相关阅读:
    【唯星宠物】——CSS/BootStrap/Jquery爬坑之响应式首页
    【可用性评估】——手机输入法可用性评估·论文
    一个简单示例看懂.Net 并行编程
    CentOS 7.1上安装.Net Core
    用 QGIS 画矢量交通路线图
    工作流服务实战
    JVM调优总结
    内存调优
    ConcurrentHashMap原理分析
    Mac上安装go环境
  • 原文地址:https://www.cnblogs.com/huangdengtao/p/12404127.html
Copyright © 2020-2023  润新知