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