•实现您自己的驱动程序(驱动程序模板)
•故障排除
本节介绍了如何显示驱动功能,并提供一个功能模板,旨在帮助您建立自己的特定于设备的驱动程序。
Android依靠在Linux / fb.h内核头文件的标准帧缓冲设备(/ dev/fb0或/ dev/graphics/fb0)和驱动程序。欲了解更多有关标准的Linux帧缓冲区信息,请参阅http://kernel.org的帧缓冲设备。
功能
在Android,每个窗口得到Surface对象实施,即SurfaceFlinger 将对象放置于framebuffer上(这就是system-wide screen composer)。每个Surface是双缓冲。后台缓冲区--drawing takes, 前台缓冲区--composition。
当unlockCanvas()被调用时,后台缓冲区是已经画完,这意味着它将被呈现,且可以再次使用。 Android翻转前后缓冲区,缓冲区确保最少量的复制,而且总是有一个缓冲被SurfaceFlinger使用, (即确保屏幕没有闪烁或显示痕迹)。
Android提出两项要求的驱动程序:一个可映射内存的线性地址空间,它可以直接写入和支持rgb_565像素格式。一个典型的帧显示包括:
•访问通过调用/ dev/fb0打开驱动
•使用FBIOGET_FSCREENINFO和FBIOGET_VSCREENINFO输入/输出控制(IOCTL)调用以检索有关屏幕信息
•使用FBIOPUT_VSCREENINFO的ioctl,试图建立一个虚拟显示两倍的物理屏幕大小和设置像素格式rgb_565。如果成功,实现双缓冲的视频内存。
当一个页面需要翻盖,Android就会再做FBIOPUT_VSCREENINFO的ioctl调用一个新的y偏移指向其他视频内存缓冲区。这个ioctl反过来调用驱动程序的fb_pan_display(),以进行实际的翻转。如果没有足够的视频内存,内存使用和定期只是到视频内存复制时,到时候做翻转。分配显存和设置像素格式后,Android使用的mmap()映射到进程的地址空间的内存。所有写入到帧缓冲通过此mmaped内存中完成。
为了保持足够的性能,帧缓冲内存应该缓存。如果您使用write-back,刷新前帧从DMA缓冲区写入到液晶缓存。如果这是不可能的,你可以使用write-through。作为最后的手段,你也可以使用未缓存的write-bugger内存,但性能会受到影响。
实现自己的驱动程序(驱动程序模板)
下面的示例驱动程序提供了一个功能的例子,以帮助您建立自己的显示驱动程序。修改PGUIDE_FB ...宏根据需要以匹配您自己的设备硬件的要求。
/** pguidefb.c** Copyright 2007, Google Inc.** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License version 2 as* published by the Free Software Foundation.*//** ANDROID PORTING GUIDE: FRAME BUFFER DRIVER TEMPLATE** This template is designed to provide the minimum frame buffer* functionality necessary for Android to display properly on a new* device. The PGUIDE_FB macros are meant as pointers indicating* where to implement the hardware specific code necessary for the new* device. The existence of the macros is not meant to trivialize the* work required, just as an indication of where the work needs to be* done.*/#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/mm.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/platform_device.h>/* Android currently only uses rgb565 in the hardware framebuffer */#define ANDROID_BYTES_PER_PIXEL 2/* Android will use double buffer in video if there is enough */#define ANDROID_NUMBER_OF_BUFFERS 2/* Modify these macros to suit the hardware */#define PGUIDE_FB_ROTATE/* Do what is necessary to cause the rotation */#define PGUIDE_FB_PAN/* Do what is necessary to cause the panning */#define PGUIDE_FB_PROBE_FIRST/* Do any early hardware initialization */#define PGUIDE_FB_PROBE_SECOND/* Do any later hardware initialization */#define PGUIDE_FB_WIDTH 320/* Return the width of the screen */#define PGUIDE_FB_HEIGHT 240/* Return the heighth of the screen */#define PGUIDE_FB_SCREEN_BASE 0/* Return the virtual address of the start of fb memory */#define PGUIDE_FB_SMEM_START PGUIDE_FB_SCREEN_BASE/* Return the physical address of the start of fb memory */#define PGUIDE_FB_REMOVE/* Do any hardware shutdown */struct pguide_fb {int rotation;struct fb_info fb;u32 cmap[16];};static inline u32 convert_bitfield(int val, struct fb_bitfield *bf){unsigned int mask = (1 << bf->length) - 1;return (val >> (16 - bf->length) & mask) << bf->offset;}/* set the software color map. Probably doesn't need modifying. */static intpguide_fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,unsigned int blue, unsigned int transp, struct fb_info *info){struct pguide_fb *fb = container_of(info, struct pguide_fb, fb);if (regno < 16) {fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |convert_bitfield(blue, &fb->fb.var.blue) |convert_bitfield(green, &fb->fb.var.green) |convert_bitfield(red, &fb->fb.var.red);return 0;}else {return 1;}}/* check var to see if supported by this device. Probably doesn't* need modifying.*/static int pguide_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){if((var->rotate & 1) != (info->var.rotate & 1)) {if((var->xres != info->var.yres) ||(var->yres != info->var.xres) ||(var->xres_virtual != info->var.yres) ||(var->yres_virtual >info->var.xres * ANDROID_NUMBER_OF_BUFFERS) ||(var->yres_virtual < info->var.xres )) {return -EINVAL;}}else {if((var->xres != info->var.xres) ||(var->yres != info->var.yres) ||(var->xres_virtual != info->var.xres) ||(var->yres_virtual >info->var.yres * ANDROID_NUMBER_OF_BUFFERS) ||(var->yres_virtual < info->var.yres )) {return -EINVAL;}}if((var->xoffset != info->var.xoffset) ||(var->bits_per_pixel != info->var.bits_per_pixel) ||(var->grayscale != info->var.grayscale)) {return -EINVAL;}return 0;}/* Handles screen rotation if device supports it. */static int pguide_fb_set_par(struct fb_info *info){struct pguide_fb *fb = container_of(info, struct pguide_fb, fb);if(fb->rotation != fb->fb.var.rotate) {info->fix.line_length =info->var.xres * ANDROID_BYTES_PER_PIXEL;fb->rotation = fb->fb.var.rotate;PGUIDE_FB_ROTATE;}return 0;}/* Pan the display if device supports it. */static int pguide_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){struct pguide_fb *fb __attribute__ ((unused))= container_of(info, struct pguide_fb, fb);/* Set the frame buffer base to something like:fb->fb.fix.smem_start + fb->fb.var.xres *ANDROID_BYTES_PER_PIXEL * var->yoffset*/PGUIDE_FB_PAN;return 0;}static struct fb_ops pguide_fb_ops = {.owner = THIS_MODULE,.fb_check_var = pguide_fb_check_var,.fb_set_par = pguide_fb_set_par,.fb_setcolreg = pguide_fb_setcolreg,.fb_pan_display = pguide_fb_pan_display,/* These are generic software based fb functions */.fb_fillrect = cfb_fillrect,.fb_copyarea = cfb_copyarea,.fb_imageblit = cfb_imageblit,};static int pguide_fb_probe(struct platform_device *pdev){int ret;struct pguide_fb *fb;size_t framesize;uint32_t width, height;fb = kzalloc(sizeof(*fb), GFP_KERNEL);if(fb == NULL) {ret = -ENOMEM;goto err_fb_alloc_failed;}platform_set_drvdata(pdev, fb);PGUIDE_FB_PROBE_FIRST;width = PGUIDE_FB_WIDTH;height = PGUIDE_FB_HEIGHT;fb->fb.fbops = &pguide_fb_ops;/* These modes are the ones currently required by Android */fb->fb.flags = FBINFO_FLAG_DEFAULT;fb->fb.pseudo_palette = fb->cmap;fb->fb.fix.type = FB_TYPE_PACKED_PIXELS;fb->fb.fix.visual = FB_VISUAL_TRUECOLOR;fb->fb.fix.line_length = width * ANDROID_BYTES_PER_PIXEL;fb->fb.fix.accel = FB_ACCEL_NONE;fb->fb.fix.ypanstep = 1;fb->fb.var.xres = width;fb->fb.var.yres = height;fb->fb.var.xres_virtual = width;fb->fb.var.yres_virtual = height * ANDROID_NUMBER_OF_BUFFERS;fb->fb.var.bits_per_pixel = 16;fb->fb.var.activate = FB_ACTIVATE_NOW;fb->fb.var.height = height;fb->fb.var.width = width;fb->fb.var.red.offset = 11;fb->fb.var.red.length = 5;fb->fb.var.green.offset = 5;fb->fb.var.green.length = 6;fb->fb.var.blue.offset = 0;fb->fb.var.blue.length = 5;framesize = width * height *ANDROID_BYTES_PER_PIXEL * ANDROID_NUMBER_OF_BUFFERS;fb->fb.screen_base = PGUIDE_FB_SCREEN_BASE;fb->fb.fix.smem_start = PGUIDE_FB_SMEM_START;fb->fb.fix.smem_len = framesize;ret = fb_set_var(&fb->fb, &fb->fb.var);if(ret)goto err_fb_set_var_failed;PGUIDE_FB_PROBE_SECOND;ret = register_framebuffer(&fb->fb);if(ret)goto err_register_framebuffer_failed;return 0;err_register_framebuffer_failed:err_fb_set_var_failed:kfree(fb);err_fb_alloc_failed:return ret;}static int pguide_fb_remove(struct platform_device *pdev){struct pguide_fb *fb = platform_get_drvdata(pdev);PGUIDE_FB_REMOVE;kfree(fb);return 0;}static struct platform_driver pguide_fb_driver = {.probe = pguide_fb_probe,.remove = pguide_fb_remove,.driver = {.name = "pguide_fb"}};static int __init pguide_fb_init(void){return platform_driver_register(&pguide_fb_driver);}static void __exit pguide_fb_exit(void){platform_driver_unregister(&pguide_fb_driver);}module_init(pguide_fb_init);module_exit(pguide_fb_exit);MODULE_LICENSE("GPL");下面的问题都具有类似的原因:
•数字键:在拨号的应用程序,当按下数字键拨打一个电话号码,该号码不显示在屏幕上,直到下一个数字后,已被按下。
•箭头键:当按下箭头键,所需的图标没有得到强调。例如,如果您通过在应用程序菜单图标浏览,您可能会注意到,当您使用箭头键来浏览选项之间时,图标预期不按您预期突出显示。
这两个问题是由于不正确的执行情况的帧缓冲区的页面翻动。关键事件被捕获,但图形界面呈现每一帧滞后。
Android上的双缓冲依靠顺利呈现页面翻转(详情请参阅功能)。
5630

被折叠的 条评论
为什么被折叠?



