浅析minigui图形引擎的初始化
// pdc->surface->pixels就是mmap创建的framebuffer对应的fb_mem起始地址,
// 所以向pdc的cur_dst写入数据,将直接反应到lcd屏幕上[luther.gliethttp]
static void _dc_move_to_1 (PDC pdc, int x, int y)
{
pdc->cur_dst = (BYTE*)pdc->surface->pixels + pdc->surface->pitch * y;
pdc->cur_dst += x;
}
InitGUI==>InitGAL
int InitGAL (void)
{
int i;
int w, h, depth;
char engine [LEN_ENGINE_NAME + 1];
char mode [LEN_MODE + 1];
#ifndef __NOUNIX__
char* env_value;
if ((env_value = getenv ("gal_engine"))) { // 环境变量中是否有定义
strncpy (engine, env_value, LEN_ENGINE_NAME);
engine [LEN_ENGINE_NAME] = '\0';
}
else
#endif
if (GetMgEtcValue ("system", "gal_engine", engine, LEN_ENGINE_NAME) < 0) {
// 环境变量中没有定义,那么接下来查找InitMgEtc()加载进来的MiniGUI.cfg配置文件
// [system]节是否有定义,我的配置文件有该定义,其值为[luther.gliethttp]
// gal_engine=fbcon或者
// gal_engine=qvfb
return ERR_CONFIG_FILE;
}
// ok, 这里engine="fbcon"
if (GAL_VideoInit (engine, 0)) { // 初始化lcd,源码见后.
GAL_VideoQuit ();
fprintf (stderr, "NEWGAL: Does not find matched engine: %s.\n", engine);
return ERR_NO_MATCH;
}
#ifndef __NOUNIX__
if ((env_value = getenv ("defaultmode"))) {
strncpy (mode, env_value, LEN_MODE);
mode [LEN_MODE] = '\0';
}
else
#endif
if (GetMgEtcValue (engine, "defaultmode", mode, LEN_MODE) < 0)
if (GetMgEtcValue ("system", "defaultmode", mode, LEN_MODE) < 0)
return ERR_CONFIG_FILE;
// 查找InitMgEtc()加载进来的MiniGUI.cfg配置文件
// defaultmode数值,我的定义为:
// [fbcon]
// defaultmode=1024x768-16bpp
if (!GAL_ParseVideoMode (mode, &w, &h, &depth)) { // 解析"1024x768-16bpp"字符串
GAL_VideoQuit ();
fprintf (stderr, "NEWGAL: bad video mode parameter: %s.\n", mode);
return ERR_CONFIG_FILE;
}
// 对于我的配置[luther.gliethttp]
// w=1024
// h=768
// depth=16
// 设置current_video为w,h和depth
// 赋值给全局量__gal_screen
if (!(__gal_screen = GAL_SetVideoMode (w, h, depth, GAL_HWPALETTE))) {
// Set the requested video mode, allocating a shadow buffer if necessary.
// 对于每个像素大于8位的video,没有palette[luther.gliethttp]
// 然后根据w,h,depth这些video属性调用FB_SetVideoMode重新设置
// video的这3个属性[luther.gliethttp]
// 这样framebuffer的ubuntu就使用这个新属性来显示了[luther.gliethttp]
// 同时FB_SetVideoMode将同样设置`
// current->pixels = mapped_mem+mapped_offset;
GAL_VideoQuit ();
fprintf (stderr, "NEWGAL: Set video mode failure.\n");
return ERR_GFX_ENGINE;
}
#ifdef _LITE_VERSION
if (w != __gal_screen->w || h != __gal_screen->h) {
fprintf (stderr, "The resolution specified in MiniGUI.cfg is not "
"the same as the actual resolution: %dx%d.\n"
"This may confuse the clients. Please change it.\n",
__gal_screen->w, __gal_screen->h);
GAL_VideoQuit ();
return ERR_GFX_ENGINE;
}
#endif
for (i = 0; i < 17; i++) {
SysPixelIndex [i] = GAL_MapRGB (__gal_screen->format,
SysPixelColor [i].r,
SysPixelColor [i].g,
SysPixelColor [i].b);
}
return 0;
}
int GAL_VideoInit (const char *driver_name, Uint32 flags)
{
GAL_VideoDevice *video;
GAL_PixelFormat vformat;
Uint32 video_flags;
/* Check to make sure we don't overwrite 'current_video' */
if ( current_video != NULL ) {
GAL_VideoQuit();
}
// 这里engine="fbcon",flags=0
video = GAL_GetVideo(driver_name); // 根据engine名字获取对应的video驱动结构体[luther.gliethttp]源码见后
if ( video == NULL ) {
return (-1);
}
video->screen = NULL;
current_video = video; // 当前current_video设置为video
/* Initialize the video subsystem */
memset(&vformat, 0, sizeof(vformat));
if ( video->VideoInit(video, &vformat) < 0 ) { // 调用FB_VideoInit,源码见后[luther.gliethttp]
// 设置this->hidden->mapped_mem内存映射地址
// 同时填充RGB分别对应的mask
// 以及x,y像素数和每像素字节数[luther.gliethttp]
GAL_VideoQuit();
return(-1);
}
/* Create a zero sized video surface of the appropriate format */
// #define GAL_SWSURFACE MEMDC_FLAG_SWSURFACE /* Surface is in system memory */
// #define GAL_HWSURFACE MEMDC_FLAG_HWSURFACE /* Surface is in video memory */
// #define GAL_VideoSurface (current_video->screen)
// 定义向system内存写入video数据
video_flags = GAL_SWSURFACE;
// 源码见后
// #define GAL_VideoSurface (current_video->screen) // 设置screen
GAL_VideoSurface = GAL_CreateRGBSurface(video_flags, 0, 0,
vformat.BitsPerPixel,
vformat.Rmask, vformat.Gmask, vformat.Bmask, 0);
if ( GAL_VideoSurface == NULL ) {
GAL_VideoQuit();
return(-1);
}
GAL_VideoSurface->video = current_video; // 指定软内存对应的硬件video.[luther.gliethttp]
video->info.vfmt = GAL_VideoSurface->format; // 获取depth,r,g,b,a的结构体[luther.gliethttp]
/* We're ready to go! */
return(0);
}
static VideoBootStrap *bootstrap[] = {
......
#ifdef _NEWGAL_ENGINE_FBCON
&FBCON_bootstrap, // 名为"fbcon"的驱动
#endif
#ifdef _NEWGAL_ENGINE_QVFB
&QVFB_bootstrap,
#endif
......
NULL
};
GAL_VideoDevice *GAL_GetVideo(const char* driver_name)
{
GAL_VideoDevice *video;
int index;
int i;
index = 0;
video = NULL;
if ( driver_name != NULL ) {
// 我们这里driver_name="fbcon";[luther.gliethttp]
for ( i=0; bootstrap[i]; ++i ) {
if ( strncmp(bootstrap[i]->name, driver_name,
strlen(bootstrap[i]->name)) == 0 ) {
if ( bootstrap[i]->available() ) { // 调用FB_Available
video = bootstrap[i]->create(index); // 调用FB_CreateDevice
break;
}
}
}
} else {
// 如果没有定义driver_name,那么
// 使用第一个可用的video驱动创建一个video.(个人觉得并不推荐)[luther.gliethttp].
for ( i=0; bootstrap[i]; ++i ) {
if ( bootstrap[i]->available() ) {
video = bootstrap[i]->create(index); // new一个video,该video内存将填充对应的video操作方法[luther.gliethttp]
if ( video != NULL ) {
break;
}
}
}
}
if (video == NULL)
return NULL;
video->name = bootstrap[i]->name; // 该video的名字,我们这里就是"fbcon"[luther.gliethttp]
/* Do some basic variable initialization */
video->screen = NULL;
video->physpal = NULL;
video->offset_x = 0;
video->offset_y = 0;
memset(&video->info, 0, (sizeof video->info));
return video;
}
VideoBootStrap FBCON_bootstrap = {
"fbcon", "Linux Framebuffer Console",
FB_Available, FB_CreateDevice
};
static int FB_Available(void)
{
int console;
const char *GAL_fbdev;
GAL_fbdev = getenv("FRAMEBUFFER");
if ( GAL_fbdev == NULL ) {
GAL_fbdev = "/dev/fb0";
}
console = open(GAL_fbdev, O_RDWR, 0);
if ( console >= 0 ) {
// 能打开/dev/fb0,说明linux已经开启framebuffer显示功能,所以返回true[luther.gliehttp]
close(console);
}
return(console >= 0);
}
static GAL_VideoDevice *FB_CreateDevice(int devindex)
{
GAL_VideoDevice *this;
/* Initialize all variables that we clean on shutdown */
this = (GAL_VideoDevice *)malloc(sizeof(GAL_VideoDevice));
if ( this ) {
memset(this, 0, (sizeof *this)); // 清0
this->hidden = (struct GAL_PrivateVideoData *)
malloc((sizeof *this->hidden));
}
if ( (this == NULL) || (this->hidden == NULL) ) {
GAL_OutOfMemory();
if ( this ) {
free(this);
}
return(0);
}
// 内存空间已经全部申请成功[luther.gliethttp]
memset(this->hidden, 0, (sizeof *this->hidden));
// #define wait_vbl (this->hidden->wait_vbl)
// #define wait_idle (this->hidden->wait_idle)
// #define mouse_fd (this->hidden->mouse_fd)
// #define keyboard_fd (this->hidden->keyboard_fd)
// #define console_fd (this->hidden->console_fd)
wait_vbl = FB_WaitVBL; // linux没有该功能,该函数将直接返回[luther.gliehttp]
wait_idle = FB_WaitIdle; // 等待设备空闲,对于framebuffer来说,也是直接返回[luther.gliethttp]
mouse_fd = -1;
keyboard_fd = -1;
/* Set the function pointers */
this->VideoInit = FB_VideoInit; // 设备初始化函数
this->ListModes = FB_ListModes;
this->SetVideoMode = FB_SetVideoMode;
this->SetColors = FB_SetColors;
this->VideoQuit = FB_VideoQuit;
#if defined(_LITE_VERSION) && !defined(_STAND_ALONE)
this->RequestHWSurface = FB_RequestHWSurface;
#endif
this->AllocHWSurface = FB_AllocHWSurface;
this->CheckHWBlit = NULL;
this->FillHWRect = NULL;
this->SetHWColorKey = NULL;
this->SetHWAlpha = NULL;
this->UpdateRects = NULL;
#if 0
this->LockHWSurface = FB_LockHWSurface;
this->UnlockHWSurface = FB_UnlockHWSurface;
this->FlipHWSurface = FB_FlipHWSurface;
#endif
this->FreeHWSurface = FB_FreeHWSurface;
this->free = FB_DeleteDevice;
return this;
}
static int FB_VideoInit(_THIS, GAL_PixelFormat *vformat)
{
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
int i;
int current_index;
unsigned int current_w;
unsigned int current_h;
const char *GAL_fbdev;
/* Initialize the library */
GAL_fbdev = getenv("FRAMEBUFFER");
if ( GAL_fbdev == NULL ) {
GAL_fbdev = "/dev/fb0";
}
console_fd = open(GAL_fbdev, O_RDWR, 0);
if ( console_fd < 0 ) {
GAL_SetError("NEWGAL>FBCON: Unable to open %s\n", GAL_fbdev);
return(-1);
}
/* Get the type of video hardware */
// 获取framebuffer参数,比如我的linux下[luther.gliethttp]
// /boot/grub/menu.lst
// 设置的启动参数为vga=0x0317
// 0x0317代表的意思为,1024*768像素,16位每像素[luther.gliethttp]
if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) {
GAL_SetError("NEWGAL>FBCON: Couldn't get console hardware info\n");
FB_VideoQuit(this);
return(-1);
}
switch (finfo.type) {
case FB_TYPE_PACKED_PIXELS:
/* Supported, no worries.. */
break;
#ifdef VGA16_FBCON_SUPPORT
case FB_TYPE_VGA_PLANES:
/* VGA16 is supported, but that's it */
if ( finfo.type_aux == FB_AUX_VGA_PLANES_VGA4 ) {
if ( ioperm(0x3b4, 0x3df - 0x3b4 + 1, 1) < 0 ) {
GAL_SetError("NEWGAL>FBCON: No I/O port permissions\n");
FB_VideoQuit(this);
return(-1);
}
this->SetVideoMode = FB_SetVGA16Mode;
break;
}
/* Fall through to unsupported case */
#endif /* VGA16_FBCON_SUPPORT */
default:
GAL_SetError("NEWGAL>FBCON: Unsupported console hardware\n");
FB_VideoQuit(this);
return(-1);
}
switch (finfo.visual) {
case FB_VISUAL_TRUECOLOR:
case FB_VISUAL_PSEUDOCOLOR:
case FB_VISUAL_STATIC_PSEUDOCOLOR:
case FB_VISUAL_DIRECTCOLOR:
break;
default:
GAL_SetError("NEWGAL>FBCON: Unsupported console hardware\n");
FB_VideoQuit(this);
return(-1);
}
#if 0
/* Check if the user wants to disable hardware acceleration */
{ const char *fb_accel;
fb_accel = getenv("GAL_FBACCEL");
if ( fb_accel ) {
finfo.accel = atoi(fb_accel);
}
}
#endif
/* Memory map the device, compensating for buggy PPC mmap() */
mapped_offset = (((long)finfo.smem_start) -
(((long)finfo.smem_start)&~(getpagesize () - 1)));
mapped_memlen = finfo.smem_len+mapped_offset;
#ifdef __uClinux__
# ifdef __TARGET_BLACKFIN__
mapped_mem = mmap(NULL, mapped_memlen,
PROT_READ|PROT_WRITE, MAP_PRIVATE, console_fd, 0);
# else
mapped_mem = mmap(NULL, mapped_memlen,
PROT_READ|PROT_WRITE, 0, console_fd, 0);
# endif
#else
// 执行内存映射[luther.gliethttp]
// #define mapped_mem (this->hidden->mapped_mem)
mapped_mem = mmap(NULL, mapped_memlen,
PROT_READ|PROT_WRITE, MAP_SHARED, console_fd, 0);
#endif
if (mapped_mem == (char *)-1) {
GAL_SetError("NEWGAL>FBCON: Unable to memory map the video hardware\n");
mapped_mem = NULL;
FB_VideoQuit(this);
return(-1);
}
/* Determine the current screen depth */
if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) {
GAL_SetError("NEWGAL>FBCON: Couldn't get console pixel format\n");
FB_VideoQuit(this);
return(-1);
}
vformat->BitsPerPixel = vinfo.bits_per_pixel; // 1个像素对应bits位数[luther.gliethttp]
if ( vformat->BitsPerPixel < 8 ) {
/* Assuming VGA16, we handle this via a shadow framebuffer */
vformat->BitsPerPixel = 8; // 强制为1个字节[luther.gliethttp]
}
for ( i=0; i<vinfo.red.length; ++i ) {
// 生成红色mask,以vinfo.red.offset位开始向高位数vinfo.red.length个位,
// 比如vinfo.red.offset等于0,
// vinfo.red.length等于5,
// 那么该for循环完毕之后
// vformat->Rmask = 0x1F;[luther.gliethttp]
vformat->Rmask <<= 1;
vformat->Rmask |= (0x00000001<<vinfo.red.offset);
}
for ( i=0; i<vinfo.green.length; ++i ) {
vformat->Gmask <<= 1;
vformat->Gmask |= (0x00000001<<vinfo.green.offset);
}
for ( i=0; i<vinfo.blue.length; ++i ) {
vformat->Bmask <<= 1;
vformat->Bmask |= (0x00000001<<vinfo.blue.offset);
}
for ( i=0; i<vinfo.transp.length; ++i ) {
// 透明色[luther.gliethttp]
vformat->Amask <<= 1;
vformat->Amask |= (0x00000001<<vinfo.transp.offset);
}
saved_vinfo = vinfo;
/* Save hardware palette, if needed */
FB_SavePalette(this, &finfo, &vinfo); // 保存调色板
/* If the I/O registers are available, memory map them so we
can take advantage of any supported hardware acceleration.
*/
if ( finfo.accel && finfo.mmio_len ) {
// 如果存在寄存器io映射,那么mmap它们,这样有些硬件特性特效,我们可以去强硬控制[luther.gliethttp]
mapped_iolen = finfo.mmio_len;
mapped_io = mmap(NULL, mapped_iolen, PROT_READ|PROT_WRITE,
MAP_SHARED, console_fd, mapped_memlen);
if ( mapped_io == (char *)-1 ) {
/* Hmm, failed to memory map I/O registers */
mapped_io = NULL;
}
}
#if defined(_LITE_VERSION) && !defined(_STAND_ALONE)
if (mgIsServer) {
#endif
/* Query for the list of available video modes */
current_w = vinfo.xres; // x轴像素数,对于vga=0x0317,该值为1024
current_h = vinfo.yres; // y轴像素数,对于vga=0x0317,该值为768 [luther.gliethtttp]
current_index = ((vinfo.bits_per_pixel+7)/8)-1; // 一个像素字节数-1.
#if defined(_LITE_VERSION) && !defined(_STAND_ALONE)
}
#endif
/* Fill in our hardware acceleration capabilities */
this->info.hw_available = 1;
this->info.video_mem = finfo.smem_len/1024;
if ( mapped_io ) {
switch (finfo.accel) {
case FB_ACCEL_MATROX_MGA2064W:
case FB_ACCEL_MATROX_MGA1064SG:
case FB_ACCEL_MATROX_MGA2164W:
case FB_ACCEL_MATROX_MGA2164W_AGP:
case FB_ACCEL_MATROX_MGAG100:
/*case FB_ACCEL_MATROX_MGAG200: G200 acceleration broken! */
case FB_ACCEL_MATROX_MGAG400:
#ifdef FBACCEL_DEBUG
fprintf(stderr, "NEWGAL>FBCON: Matrox hardware accelerator!\n");
#endif
FB_MatroxAccel(this, finfo.accel);
break;
case FB_ACCEL_3DFX_BANSHEE:
#ifdef FBACCEL_DEBUG
fprintf(stderr, "NEWGAL>FBCON: 3DFX hardware accelerator!\n");
#endif
FB_3DfxAccel (this, finfo.accel);
break;
#ifdef FB_ACCEL_NEOMAGIC_NM2070
case FB_ACCEL_NEOMAGIC_NM2200:
case FB_ACCEL_NEOMAGIC_NM2230:
case FB_ACCEL_NEOMAGIC_NM2360:
case FB_ACCEL_NEOMAGIC_NM2380:
#ifdef FBACCEL_DEBUG
fprintf(stderr, "NEWGAL>FBCON: NeoMagic hardware accelerator!\n");
#endif
FB_NeoMagicAccel (this, finfo.accel);
#endif
break;
default:
#ifdef FBACCEL_DEBUG
fprintf(stderr, "NEWGAL>FBCON: Unknown hardware accelerator!\n");
#endif
break;
}
}
if (FB_OpenKeyboard(this) < 0) { // 我们这里函数FB_OpenKeyboard直接返回
FB_VideoQuit(this);
return(-1);
}
/* We're done! */
return(0);
}
GAL_Surface * GAL_CreateRGBSurface (Uint32 flags,
int width, int height, int depth,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
{
GAL_VideoDevice *video = current_video;
GAL_VideoDevice *this = current_video;
GAL_Surface *screen;
GAL_Surface *surface;
/* Check to see if we desire the surface in video memory */
if ( video ) {
// #define GAL_PublicSurface (current_video->screen)
screen = GAL_PublicSurface;
} else {
screen = NULL;
}
if ( screen && ((screen->flags&GAL_HWSURFACE) == GAL_HWSURFACE) ) {
// 表示为硬件framebuffer对应的screen缓冲区
// 我们的flags = GAL_SWSURFACE; 软接口
if ( (flags&(GAL_SRCCOLORKEY|GAL_SRCALPHA)) != 0 ) {
flags |= GAL_HWSURFACE;
}
if ( (flags & GAL_SRCCOLORKEY) == GAL_SRCCOLORKEY ) {
if ( ! current_video->info.blit_hw_CC ) {
flags &= ~GAL_HWSURFACE;
}
}
if ( (flags & GAL_SRCALPHA) == GAL_SRCALPHA ) {
if ( ! current_video->info.blit_hw_A ) {
flags &= ~GAL_HWSURFACE;
}
}
} else {
flags &= ~GAL_HWSURFACE; // 不能使用硬件缓冲区
}
/* Allocate the surface */
surface = (GAL_Surface *)malloc(sizeof(*surface)); // 申请内存
if ( surface == NULL ) {
GAL_OutOfMemory();
return(NULL);
}
if ((flags & GAL_HWSURFACE) == GAL_HWSURFACE)
surface->video = current_video; // 挂上它对应的物理video
else
surface->video = NULL; // GAL_SWSURFACE; 软接口,所以没有物理video
surface->flags = GAL_SWSURFACE; // 为软接口,并且它的video为NULL.
if ( (flags & GAL_HWSURFACE) == GAL_HWSURFACE ) {
depth = screen->format->BitsPerPixel;
Rmask = screen->format->Rmask;
Gmask = screen->format->Gmask;
Bmask = screen->format->Bmask;
Amask = screen->format->Amask;
}
// depth为一个像素对应字节数
// RGBA分别对应红绿蓝和透明色对应的mask掩码值[luther.gliethttp]
surface->format = GAL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask);
if ( surface->format == NULL ) {
free(surface);
return(NULL);
}
if ( Amask ) {
surface->flags |= GAL_SRCALPHA; // 含有透明色
}
surface->w = width;
surface->h = height;
surface->pitch = GAL_CalculatePitch(surface);
surface->pixels = NULL;
surface->offset = 0;
surface->hwdata = NULL;
surface->map = NULL;
surface->format_version = 0;
GAL_SetClipRect(surface, NULL);
/* Get the pixels */
if ( ((flags&GAL_HWSURFACE) == GAL_SWSURFACE) ||
(video->AllocHWSurface(this, surface) < 0) ) {
if ( surface->w && surface->h ) { // 我们这里w和h都定义为0[luther.gliethttp]
// pitch为屏幕一行像素所占字节数
// surface->h为一个屏幕一共多少行
// 所以它们2个相乘之后,就是整个屏幕所需内存大小[luther.gliethttp]
surface->pixels = malloc(surface->h*surface->pitch); // 申请屏幕所有像素对应的字节内存[luther.gliethttp]
if ( surface->pixels == NULL ) {
GAL_FreeSurface(surface);
GAL_OutOfMemory();
return(NULL);
}
/* This is important for bitmaps */
memset(surface->pixels, 0, surface->h*surface->pitch); // 清空内存数据
surface->flags &= ~GAL_HWSURFACE; // 软内存空间标志
}
}
/* Allocate an empty mapping */
surface->map = GAL_AllocBlitMap();
if ( surface->map == NULL ) {
GAL_FreeSurface(surface);
return(NULL);
}
/* The surface is ready to go */
surface->refcount = 1; // ok了
#ifdef CHECK_LEAKS
++surfaces_allocated;
#endif
return(surface);
}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。