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);
    }
}

猜你喜欢

转载自www.cnblogs.com/huangdengtao/p/12404127.html