目录
二、去实现上面的统一的结构体(struct DispOpr)
一、数据结构抽象
从两个不同设备中抽象出一个相同的结构体。
display_manager.h
#ifndef _DISPLAY_MANAGER_H
#define _DISPLAY_MANAGER_H
typedef struct Region{
int iLeftUpx;
int iLeftUpf;
int iWidth;
int iHeigh;
}Region, *PRegion;
typedef struct DispOpr{
char *name;
char *GetBuffer(int *pXres, int *pYres, int *pBpp);
int FlushRegion(PRegion ptRegion, char *buffer);
struct DispOpr *ptNext;
}DispOpr, *PDispOpr;
#endif
二、Framebuffer编程
根据这个结构体,完善具体的代码,编写所需要的函数。
static DispOpr g_tFramebufferOpr = {
.name = "fb",
.DeviceInit = FbDeviceInit,
.DeviceExit = FbDeviceExit,
.GetBuffer = GetBuffer,
.FlushRegion = FbFlushRegion,
};
三、显示编程
1.大概思路
下面的代码会构造各自的g_tFramebufferOpr结构体,需要用一个链表将他们管理起来
使用一个函数将他们放入链表
framebuffer.c中需要有个函数将g_tFramebufferOpr注册进链表中
2.具体步骤:
1.应用程序首先调用DispInit,DispInit会去调用到底层的初始化函数FramebufferInit
2.FramebufferInit里会去调用注册函数RegisterDisplay,注册LCD硬件相关的结构体g_tFramebufferOpr
3.注册函数RegisterDisplay,会把这些结构体放入链表
4.假设这个链表里有很多项,需要调用SelectDefaultDisplay来选择默认得输出设备
5.选择好之后,还要去调用InitDefaultDisplay来初始化这个设备
6.然后就可以调用PutPixel函数在上面绘制图片了
7.在调用FbFlushRegion把绘制好的这块区域刷到硬件上去
四、单元测试
void lcd_put_ascii(int x, int y, unsigned char c)
{
unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];
int i, b;
unsigned char byte;
for (i = 0; i < 16; i++)
{
byte = dots[i];
for (b = 7; b >= 0; b--)
{
if (byte & (1<<b))
{
/* show */
PutPixel(x+7-b, y+i, 0xffffff); /* 白 */
}
else
{
/* hide */
PutPixel(x+7-b, y+i, 0); /* 黑 */
}
}
}
}
int main(int argc, char **argv)
{
Region region;
PDispBuff ptBuffer;
DisplayInit();
SelectDefaultDisplay("fb");
InitDefaultDisplay();
lcd_put_ascii(100, 100, 'A');
region.iLeftUpX = 100;
region.iLeftUpY = 100;
region.iWidth = 8;
region.iHeigh = 16;
ptBuffer = GetDisplayBuffer();
FlushDisplayRegion(®ion, ptBuffer);
return 0;
}
五、总结
对于学习显示系统框架的总结:
对于两个不同的设备,我们要抽象出同一个结构体/结构体类型
在后面的实现中,他们要分别实现自己的结构体
一、抽象出统一的结构体:
以绘制一个按钮为例: 首先,我们要获得一个buffer,我们可以在这个buffer里进行绘制,这个buffer可以用一个结构体来表示
绘制好某个区域之后,我们需要把这个区域刷到设备上去
如何去构造这个结构体:
第一,这个结构体有名字,我们可以通过这个名字取得不同的结构体
第二,设备初始化,也就是获得设备信息;有初始化也要有退出函数。
第三,应用程序想要去绘制图片,首先我们需要有个buffer,所以我们要去获得一个buffer
第四,绘制好之后,我们需要把那块区域刷到设备上,这块区域我也可以用一个结构体来表示
我们可以从多个设备中选择一个,所以我们还应该加一个链表
这样我们就抽象出了统一的结构体
typedef struct DispOpr {
char name;
int (DeviceInit)(void);
int (DeviceExit)(void);
int (GetBuffer)(PDispBuff ptDispBuff);
int (*FlushRegion)(PRegion ptRegion, PDispBuff ptDispBuff);
struct DispOpr *ptNext;
}DispOpr, *PDispOpr;
这是buffer和区域的结构体
typedef struct DispBuff {
int iXres; int iYres;
int iBpp; char *buff;
}DispBuff, *PDispBuff;
typedef struct Region {
int iLeftUpX; int iLeftUpY;
int iWidth; int iHeigh;
}Region, *PRegion;
以后,上层的代码,调用这些结构体,就可以显示数据了。
二、去实现上面的统一的结构体(struct DispOpr)
你想将绘制好的图片在什么设备上面显示,用那个具体的设备去实现上面的结构体。
三、抽象出一个用来选择显示设备的代码
第一、管理各个设备的结构体,通过统一结构体中的链表去管理。
为下层代码提供一个注册函数,将这些结构体放入链表
下层代码又将这个注册函数封装进自己的注册函数中,将自己构造的结构体注册到上层的链表中
第二、写一个函数去调用底层不同设备注册函数
第三、写一个去选择注册哪个设备的函数,将链表头的name和传入的name比较,如果找到了就再定义一个结构体,将他存进去
第四、找到选择的设备后,需要去初始化这个设备,获得这个设备的信息,将信息放入buffer结构体中
第五、实现描点函数
第六、提供一个将绘制好后的图片,刷到设备某个位置上去的函数,这函数主要是用来获得要刷的位置信息。