现在的位置: 首页 > 综合 > 正文

GUI_成长历程_part4

2013年01月22日 ⁄ 综合 ⁄ 共 12253字 ⁄ 字号 评论关闭

名    称: GUI_成长历程_part4
文    件:OpenglLcd.h
          OpenglLcd.c
/*****************************************************************************************
                                    OpenGL模拟显示屏
文 件 名: OpenglLcd.h
模块功能:模拟显示器
颜色模式:固定为565模式
编译环境:VS2008
系统环境:有无ucosii,都可以. 会自动创建显示屏需要的2个线程
改    进: 画点函数很快。画面刷新频率可以控制了,可以让出很多CPU。
编    者: 张永辉 2012-12-17
修    改:添加GlDisBmp函数 2012-12-26
修    改:添加模拟触摸屏返回x y位置函数 2012-12-28
*****************************************************************************************/
#ifndef __OPENGLLCD__H
#define __OPENGLLCD__H
/****************************************************************************************/
//#include "LCDConf.h"                          //要用到里面的配置

#define u16 unsigned short                      //数据长度。
#define u32 unsigned int
#define u8  unsigned char                       //数据长度。

#ifdef LCD_XSIZE
    #define X_SIZE LCD_XSIZE                    //定义屏幕尺寸 GUIConf.h
    #define Y_SIZE LCD_YSIZE
#else
    #define X_SIZE 480
    #define Y_SIZE 272
#endif
#define GL_FREASH_TIME()    Sleep(1)            //屏幕刷新时间间隔 1000/1/10=100Hz 建议不要改次设置

//****************************************************************************************
//RGB565 bmp图片信息结构体
typedef struct TUserBmp
{
    u16 w;          //图片的X_SIZE 宽
    u16 h;          //图片的Y_SIZE 高
    u16* data;      //RGB565颜色格式的数据指针。可以是arry[][]格式;
};

extern  u16 GlDisBuff[Y_SIZE][X_SIZE];          //显存区。向此写入数据即可改变颜色.与显示屏的接口。
/*****************************************************************************************
                                    颜色定义
*****************************************************************************************/
#define COLOUR_CLEAR 0XFFFF                     //调用GlInit() GlDisClear()后的显示屏颜色

/*****************************************************************************************
                                    功能函数
*****************************************************************************************/
void    GlInit(void);                           //初始化后即会创建2个windows线程,以运行GL。

//----------------------------------显示--------------------------------------------------
void    GlDisTset(void);                        //测试,将显示屏画RBG三个色后返回
void    GlDisPoint(u32 x,u32 y, u16 Color);     //描点函数
u16     GlDisPointGet(u32 x,u32 y);             //返回某点颜色
void    GlDisClear(void);                       //清屏
//x0    y0      :显示的开始位置
//Xsize Ysize   :要显示的区域大小
//bmpinfo       :要显示的图片信息
void    GlDisBmp(u32 x0,u32 y0,u32 Xsize,u32 Ysize, const struct TUserBmp * bmpinfo);
//----------------------------------时间--------------------------------------------------
u32     GlTimeGetMs(void);                      //单位=GL_FREASH_TIME(),强烈建议GL_FREASH_TIME=1ms
void    GlTimeDelayMs(u32 time);
//----------------------------------键盘--------------------------------------------------
//函数功能:有按键时的回调函数                  //以下是回调函数,应该在本模块之外实现。删除模块内的。
//传入参数: key 按下的值
//          x  y当前鼠标的位置。左上脚=00。鼠标在预定显示屏外也能获取到鼠标。
void    GlKeyCallBacdk(unsigned char key,int x,int y);

//----------------------------------鼠标--------------------------------------------------
//鼠标位置跟踪                                  //以下是回调函数,应该在本模块之外实现。删除模块内的。
//被 调 用:鼠标移动位置时 左右滚轮放开时
//不被调用:左右滚轮按下或按下拖动时
//参    数:鼠标位置
void    GlMouseMoveCallBack(int x,int y);

//鼠标按下时位置跟踪
//被 调 用:左右键滚轮按下后 而且在移动位置时
void    GlMouseClickMoveCallBack(int x,int y);

//鼠标单击
//被 调 用:左右键滚轮 按下或放开时都会被调用
//参    数:button = 0 左键      state = 0 按下     x:X位置
//          button = 1 滚轮      state = 1 放开     y:Y位置
//          button = 2 右键
void    GlMouseClickCallBack(int button,int state,int x,int y);
//返回电阻触摸屏的X方向转换值,如果未按下返回-1
int     GlTouchGetAdX(void);
//返回电阻触摸屏的Y方向转换值,如果未按下返回-1
int     GlTouchGetAdY(void);
/****************************************************************************************/
#endif
/*****************************************************************************************
                                    OpenGL模拟显示屏
文 件 名: OpenglLcd.c
*****************************************************************************************/
#include<Windows.h>
#include<process.h>                 //_beginthread

#include <GL/glut.h>
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "glut32.lib")
#include "OpenglLcd.h"
/****************************************************************************************/
//静态变量
static u32   FreshFlg = 0;
static const GLint      ImageWidth =X_SIZE;         //使用OpenGL的GLint类型,它是32位的。
static const GLint      ImageHeight=Y_SIZE;
static GLint            ImagelLength;               //图像缓冲占的字节长度
static GLubyte*         ImageDataP;                 //图像缓冲区指针更改该区域的值即可改变图像
static u32              SysTimeMs;                  //记录系统开机以来运行了的时间。与GL_FREASH_TIME相关

static int              TouchADx;                   //使用鼠标按下模拟触摸屏
static int              TouchADy;

u16     GlDisBuff[Y_SIZE][X_SIZE];                  //显存区
/****************************************************************************************/
//两个任务
void static GlTaskStart (void * arg);
void static GlTaskDisBuffCopy(void * arg);
/*****************************************************************************************
                                    初始化函数
在OSInit()之后,OSStart()之前调用
*****************************************************************************************/

void GlInit(void)
{
    u32 x , y;

    //--------------------显示屏初始化----------------------
    //给背景色
    for(y = 0; y < Y_SIZE ; y++)
    {
        for(x = 0; x < X_SIZE ; x++)
        {
            GlDisBuff[y][x] = COLOUR_CLEAR;
        }
    }

    //任务:GL将显存的颜色显示到显示屏
    //      设置键盘按键回调函数
    _beginthread(GlTaskStart,0,NULL);

    //任务:将GlDisBuff的颜色刷新到显存
    _beginthread(GlTaskDisBuffCopy,0,NULL);
}
/*****************************************************************************************
                                    功能函数集
*****************************************************************************************/
//----------------------------------显示--------------------------------------------------
//函数功能:性能测试 功能测试函数
void GlDisTset(void)
{
    int x = 0;
    int y = 0;

    //绘制红色区域块
    for(x = 0;x < X_SIZE/3; x++)
    {
        for(y = 0;y <= Y_SIZE;y++)
        {
            GlDisPoint(x,y,0x1f<<11);
        }
    }

    //绘制绿色区域块
    for(x = X_SIZE/3; x < 2*X_SIZE/3; x++)
    {
        for(y = 0;y <= Y_SIZE;y++)
        {
            GlDisPoint(x,y,0x3f<<5);
        }
    }

    //绘制蓝色区域块
    for(x = 2*X_SIZE/3; x <= X_SIZE; x++)
    {
        for(y = 0;y <= Y_SIZE;y++)
        {
            GlDisPoint(x,y,0x1f);
        }
    }

    Sleep(1000);
    GlDisClear();
}

//----------------------------------显示--------------------------------------------------
//函数功能:清屏
void GlDisClear(void)
{
    u32 x , y;
    for(y = 0; y < Y_SIZE ; y++)
    {
        for(x = 0; x < X_SIZE ; x++)
        {
            GlDisBuff[y][x] = COLOUR_CLEAR;
        }
    }
}
//函数功能:在屏幕上画点
//      x :    x坐标位置 0... X_SIZE-1
//      y :    y坐标位置 0... Y_SIZE-1
//      C :    点的颜色  0... 65535  RGB565模式
//坐 标 系:左上角(0,0)  右下角(X_SIZE,Y_SIZE)
void    GlDisPoint(u32 x,u32 y, u16 Color)
{
    if(x >= X_SIZE || y >= Y_SIZE)
    {
        return;
    }
    GlDisBuff[y][x] = Color;
}
//函数功能:获取某点的颜色
//      x :    x坐标位置 0... X_SIZE-1
//      y :    y坐标位置 0... Y_SIZE-1
//      C :    点的颜色  0... 65535  RGB565模式
//坐 标 系:左上角(0,0)  右下角(X_SIZE,Y_SIZE)
u16   GlDisPointGet(u32 x,u32 y)
{
    if(x >= X_SIZE || y >= Y_SIZE)
    {
        return 0;
    }
    return GlDisBuff[y][x];
}
//函数功能:在某区域显示RGB565格式的图片
//x0    y0      :显示的开始位置
//Xsize Ysize   :要显示的区域大小
//bmpinfo       :要显示的图片信息
void   GlDisBmp(u32 x0,u32 y0,u32 Xsize,u32 Ysize, const struct TUserBmp* bmpinfo)
{
    u16 *pbmp = (u16 *)bmpinfo->data;
    u16 x0copy;
    u16 hcnt;

    //防止输入参数大于实际像素长度
    Xsize=(Xsize < bmpinfo->w )?Xsize:bmpinfo->w;
    Ysize=(Ysize < bmpinfo->h )?Ysize:bmpinfo->h;

    //[(x0 y0) (Xsize Ysize)]作为边界
    Xsize = (x0 + Xsize)<(X_SIZE)?(x0 + Xsize):X_SIZE;
    Ysize = (y0 + Ysize)<(Y_SIZE)?(y0 + Ysize):Y_SIZE;

    x0copy = x0;    //x0的备份
    hcnt = 0;       //对行计数
    for(;y0 < Ysize;y0++)
    {
        for(x0 = x0copy;x0 < Xsize;x0++)
        {
            GlDisBuff[y0][x0] = *pbmp++;
        }
        hcnt++;
        pbmp = bmpinfo->data + hcnt*(bmpinfo->w);
    }
}
//----------------------------------时间--------------------------------------------------
//函数功能:获取系统时间
//单位    :本质是对GL_FREASH_TIME的计数
u32  GlTimeGetMs(void)
{
    return SysTimeMs;
}
void    GlTimeDelayMs(u32 time)
{
    Sleep(time);
}
//----------------------------------键盘--------------------------------------------------
//函数功能:有按键时的回调函数
//传入参数: key 按下的值
//          x  y当前鼠标的位置。左上脚=00。鼠标在预定显示屏外也能获取到鼠标。
void GlKeyCallBacdk(unsigned char key,int x,int y)
{
    //printf("key = %c ",key);
    //printf("post x= %d y= %d\n",x,y);
}

//----------------------------------鼠标--------------------------------------------------
//鼠标位置跟踪
//被 调 用:鼠标移动位置时 左右滚轮放开时
//不被调用:左右滚轮按下或按下拖动时
//参    数:鼠标位置
void GlMouseMoveCallBack(int x,int y)
{
    //printf("post x= %d y= %d\n",x,y);
    //GlDisPoint(x,y,0xf100);
}

//鼠标按下时位置跟踪
//被 调 用:左右键滚轮按下后 而且在移动位置时
void GlMouseClickMoveCallBack(int x,int y)
{
    //printf("-----post x= %d y= %d\n",x,y);
    TouchADx = x;
    TouchADy = y;
}

//鼠标单击
//被 调 用:左右键滚轮 按下或放开时都会被调用
//参    数:button = 0 左键      state = 0 按下     x:X位置
//          button = 1 滚轮      state = 1 放开     y:Y位置
//          button = 2 右键
void GlMouseClickCallBack(int button,int state,int x,int y)
{
    //printf("button= %d state= %d x=%d y=%d\n",button,state,x,y);
    TouchADx = x;
    TouchADy = y;
    if(state==1)
    {
        TouchADx = -1;
        TouchADy = -1;
    }
}
//返回电阻触摸屏的X方向转换值
int GlTouchGetAdX(void)
{
    return TouchADx;
}
//返回电阻触摸屏的Y方向转换值
int GlTouchGetAdY(void)
{
    return TouchADy;
}
/*****************************************************************************************
                                任务函数:GlTaskDisBuffCopy
任务:将GlDisBuff的颜色刷新到显存
*****************************************************************************************/
void static GlTaskDisBuffCopy(void * arg)
{
    GLint post,ypost;
    GLubyte fr,fg,fb;

    u32 x , y;
    u16 Color;

    arg = arg;

    //等待 GlTaskStart() 给ImageDataP分配储存空间后才能对ImageDataP操作。
    GL_FREASH_TIME();
    GL_FREASH_TIME();

    while(1)
    {
        //决定刷新频率
        GL_FREASH_TIME();
        SysTimeMs++;
        if (SysTimeMs%10 != 0)
        {
            continue;
        }
        //把颜色从GlDisBuff复制到ImageDataP
        for(y = 0; y < Y_SIZE ; y++)
        {
            ypost = (Y_SIZE-1-y)*X_SIZE;    //计算y坐标
            for(x = 0; x < X_SIZE ; x++)
            {
                //颜色变换 将565变成24位模式
                Color = GlDisBuff[y][x];
                fr = (GLubyte)((Color >> 8)|(0x07));
                fg = (GLubyte)((Color >> 3)|(0x03));
                fb = (GLubyte)((Color << 3));
                //坐标变换 ImageDataP坐标是:按笛卡尔坐标系的第一象限,x=[0 ... X_SIZE-1]  y=[0 ... Y_SIZE-1]
                post = (ypost + x)*3;
                //向缓冲区写入一个点的颜色
                ImageDataP[post]   = fr;    //R
                ImageDataP[post+1] = fg;    //G
                ImageDataP[post+2] = fb;    //B
            }
        }
        FreshFlg = 1;                       //与GlTaskStart()任务保持同步
    }
}
/*****************************************************************************************
                                任务函数:GlTaskStart
任务:GL将内存的颜色显示到显示屏
*****************************************************************************************/
void static GL_Display(void);       //显示处理回调函数
void static GL_Idle(void);          //CPU空闲时自动回调用的函数
//----------------------------------------------------------------------------------------
//函数功能:GL任务
void static GlTaskStart (void * arg)
{
    arg = arg;

    //-------------------图形配置---------------------------
    //计算图像大小
    ImagelLength = ImageWidth *  3;                 //每个像素3字节
    while(  ImagelLength % 4 != 0 )                 //修正LineLength使其为4的倍数
    {
        ++ImagelLength;                             //每一行像素数据的长度若不是4的倍数则填充数据使它是4的倍数
    }
    ImagelLength *=  ImageHeight;                   //PixelLength = ImageWidth*3*ImageHeight

    //申请图像缓冲区
    ImageDataP = (GLubyte*)malloc(ImagelLength);

    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);    //修改了参数为GLUT_DOUBLE
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(X_SIZE,  Y_SIZE);
    glutCreateWindow("华丽的显示屏");               //窗口标题
    glutDisplayFunc(&GL_Display);
    glutIdleFunc(&GL_Idle);                         //新加入了这句
    FreshFlg = 1;

    //------------------按键配置----------------------------
    glutKeyboardFunc(GlKeyCallBacdk);               //设置回调函数即可

    //------------------鼠标配置----------------------------
    glutPassiveMotionFunc(GlMouseMoveCallBack);     //鼠标位置跟踪

    glutMotionFunc(GlMouseClickMoveCallBack);       //鼠标位置跟踪 有按下后

    glutMouseFunc(GlMouseClickCallBack);            //鼠标按下,放开

    //-------------------配置完成---------------------------
    glutMainLoop();
    free(ImageDataP);

    while (1)
    {
        GL_FREASH_TIME();
    }
}

void static GL_Display(void)
{
    //glClear(GL_COLOR_BUFFER_BIT);//可以不要清屏,因为每次绘制时,画面都覆盖整个屏幕
    //绘制像素
    glDrawPixels(ImageWidth, ImageHeight,GL_BGR_EXT,GL_UNSIGNED_BYTE,ImageDataP);
    //完成绘制
    glutSwapBuffers();
}

void static GL_Idle(void)
{
    //在CPU空闲时调用. 在这里可以添加程序,使扫描速度降低。
    if(FreshFlg == 0)
    {
        return;
    }
    FreshFlg = 0;                                   //同步

    GL_Display();
}

【上篇】
【下篇】

抱歉!评论已关闭.