framebuffer机制是linux显示技术的一个抽象,它对用户屏蔽了不同的硬件(显示)实现,将不同的硬件实现抽象为一个通用的文件节点/dev/fb0,并提供针对该节点的一组通用的ioctrl操作方式。因此对一个应用程序而言,想要在屏幕上进行绘制时只需要打开这个节点并通过ioctrl操作之,而不必关心设备具体用了哪个厂家的显示设备
android上有现成的实现代码和公共操作接口供调用(bootable/recovery/minui/),可参考
http://osxr.org/android/source/bootable/recovery/minui/?v=android-4.4.4_r1
本文仅仅是一个示例程序,基于上述minui库实现。
以下为代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "minui.h"
//==================== debug ====================
#define ENTER \
do{ printf("[FB_DBG] func: %s line: %04d\n", __func__, __LINE__); }while(0)
#define PRINT_DBG(format,x...) \
do{ printf("[FB_DBG] " format, ## x); }while(0)
#define PRINT_INFO(format,x...) \
do{ printf("[FB_INFO] " format, ## x); }while(0)
#define PRINT_WARN(format,x...) \
do{ printf("[FB_WARN] " format, ## x); }while(0)
#define PRINT_ERR(format,x...) \
do{ printf("[FB_ERR] func: %s line: %04d info: " format, __func__, __LINE__, ## x); }while(0)
//==================== debug ====================
gr_surface fb_surface;
//不知什么原因,这个gr_text的y参数更像是每一行文字的下边沿坐标,因此我用gr_text_wrap对其做了包裹:强制对其y坐标加20个像素。
//这样,当你调用gr_text_wrap时便可以将传入的x、y坐标当作每一行文字的左上角坐标了。不知道文字的高度和宽度怎么调整,所以只有左上角坐标就可以了。
int gr_text_wrap(int x, int y, const char *s)
{
return gr_text(x, y+20, s);
}
void fb_draw_image()
{
PRINT_INFO("fb_draw_image\n");
struct timeval time_start,time_end;
int width = gr_get_width(fb_surface);
int height = gr_get_height(fb_surface);
int dx = (gr_fb_width() - width)/2;
int dy = (gr_fb_height() - height)/2;
gettimeofday(&time_start,NULL);
PRINT_INFO("show picture for 1 seconds\n");
while(1) {
//refresh this image continuely for 1 seconds
gr_blit(fb_surface, 0, 0, width, height, dx, dy);
gr_flip();
gettimeofday(&time_end,NULL);
if((time_end.tv_sec - time_start.tv_sec) >= 1) {
PRINT_INFO("show picture end\n");
break;
}
}
res_free_surface(fb_surface);
}
void fb_load_image(char *image)
{
PRINT_INFO("fb_load_image\n");
int result = res_create_surface(image, &fb_surface);
if (result < 0) {
if (result == -2) {
PRINT_INFO("Bitmap %s missing header\n",image );
} else {
PRINT_ERR("Missing bitmap %s\n(Code %d)\n", image, result);
}
fb_surface = NULL;
}
else
fb_draw_image();
}
void fb_fill_line_green(void)
{
gr_color(0, 255, 0, 255);
gr_fill(0, 0, gr_fb_width(), 40);//绘制矩形区域:前两个参数是左上角的坐标(x,y),后两个参数是右下角的坐标(x,y)
gr_flip();
PRINT_INFO("fill line with green\n");
}
void fb_fill_line_red(void)
{
gr_color(255, 0, 0, 255);
gr_fill(0, 0, gr_fb_width(), 40);
gr_flip();
PRINT_INFO("fill line with red\n");
}
void fb_fill_full_white(void)
{
gr_color(255, 255, 255, 255);
gr_fill(0, 0, gr_fb_width(), gr_fb_height());
gr_flip();
PRINT_INFO("fill full with white\n");
}
void fb_fill_full_black(void)
{
gr_color(0, 0, 0, 255);
gr_fill(0, 0, gr_fb_width(), gr_fb_height());
gr_flip();
PRINT_INFO("fill full with black\n");
}
void fb_show_success(int x, int y)
{
PRINT_INFO("show success logo\n");
int curr_y=y;
int offset_y=10;
int offset_x=0;
int i=0;
gr_color(0, 255, 0, 255);//GREEN
while(i<10) {
gr_text_wrap(x+offset_x,curr_y+=offset_y," ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y,"## ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ## ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ## ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ## ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ####");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ##");
offset_x+=1;
curr_y=y;
i++;
}
gr_flip();
}
void fb_show_failed(int x, int y)
{
PRINT_INFO("show failed logo\n");
int curr_y=y;
int offset_y=10;
int offset_x=0;
int i=0;
gr_color(255, 0, 0, 255);//RED
while(i<10) {
gr_text_wrap(x+offset_x,curr_y+=offset_y,"## ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ## ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ## ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ## ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ## ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ###");
gr_text_wrap(x+offset_x,curr_y+=offset_y," #");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ###");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ## ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ## ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ## ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y," ## ##");
gr_text_wrap(x+offset_x,curr_y+=offset_y,"## ##");
offset_x+=1;
curr_y=y;
i++;
}
gr_flip();
}
void fb_print_info(char* msg)
{
fb_fill_full_white();
fb_fill_line_green();
gr_color(0, 0, 0, 255);//BLACK
PRINT_INFO("show the text\n");
gr_text_wrap(0,0,msg);
gr_flip();
fb_show_success(200, 300);
}
void fb_print_error(char* msg)
{
fb_fill_full_white();
fb_fill_line_red();
gr_color(255, 255, 0, 255);//YELLOW
PRINT_INFO("show the text\n");
gr_text_wrap(0,0,msg);
gr_flip();
fb_show_failed(200, 300);
}
void fb_test(void)
{
PRINT_INFO("start framebuffer test\n");
PRINT_INFO("clean and refresh the screen\n");
gr_clean();
fb_fill_full_white();
sleep(1);
fb_fill_full_black();
sleep(1);
fb_fill_full_white();
sleep(1);
fb_fill_line_green();
sleep(1);
fb_fill_line_red();
sleep(1);
fb_print_info("success !!!!!");
sleep(1);
fb_print_error("failed !!!!!");
sleep(1);
fb_load_image("tangwei");
PRINT_INFO("fb_test Exit\n");
}
int main(int argc, char **argv)
{
gr_init();
gr_clean();
PRINT_INFO("frambuffer init\n");
fb_test();
PRINT_INFO("Exit\n");
return 0;
}