Android2.0/2.1系统中,S3C6410双Framebuffer显示问题的解决方法
前文Problems with S3C6410 double framebuffer in Android找到了Android系统处理三星S3C6410处理器的双Framebuffer驱动时出现的屏闪问题。这两天分析了三星原厂提供的cupcake代码后,终于找到解决方法。
Android2.0之后,Google把和Framebuffer打交道的EGL显示部分也抽象为一个HAL模块——Gralloc
cupcake中用于swapbuffer也被移到了Gralloc下的Framebuffer.cpp文件中,具体函数变为fb_post:
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
{
if (private_handle_t::validate(buffer) < 0)
return -EINVAL;
fb_context_t* ctx = (fb_context_t*)dev;
private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer);
private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);
if (m->currentBuffer) {
m->base.unlock(&m->base, m->currentBuffer);
m->currentBuffer = 0;
}
if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
m->base.lock(&m->base, buffer,
private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
0, 0, m->info.xres, m->info.yres, NULL);
const size_t offset = hnd->base - m->framebuffer->base;
m->info.activate = FB_ACTIVATE_VBL;
m->info.yoffset = offset / m->finfo.line_length;
if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
LOGE("FBIOPUT_VSCREENINFO failed");
m->base.unlock(&m->base, buffer);
return -errno;
}
m->currentBuffer = buffer;
} else {
// If we can't do the page_flip, just copy the buffer to the front
// FIXME: use copybit HAL instead of memcpy
void* fb_vaddr;
void* buffer_vaddr;
m->base.lock(&m->base, m->framebuffer,
GRALLOC_USAGE_SW_WRITE_RARELY,
0, 0, m->info.xres, m->info.yres,
&fb_vaddr);
m->base.lock(&m->base, buffer,
GRALLOC_USAGE_SW_READ_RARELY,
0, 0, m->info.xres, m->info.yres,
&buffer_vaddr);
memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);
m->base.unlock(&m->base, buffer);
m->base.unlock(&m->base, m->framebuffer);
}
return 0;
}
=======================================================================
函数名称变了,应该是实现方法有所改变,不是直接贴swap,而是采用时间间隔来post。
但最底层的处理方法不会变,还是用FBIOPUT_VSCREENINFO。
同样,用PAN_DISPLAY修改即可。
if (ioctl(m->framebuffer->fd, FBIOPAN_DISPLAY, &m->info) < 0)
{
LOGE("%s::FBIOPAN_DISPLAY fail(%s)", __func__, strerror(errno));
return 0;
}
unsigned int crtc = 0;
if(ioctl(m->framebuffer->fd, FBIO_WAITFORVSYNC, &crtc) < 0) {
//s3cfb_wait_for_vsync->wait_event_interruptible_timeout
LOGE("%s::FBIO_WAITFORVSYNC fail(%s)", __func__, strerror(errno));
return 0;
}
/* if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1)
{
LOGE("FBIOPUT_VSCREENINFO failed");
m->base.unlock(&m->base, buffer);
return -errno;
}
*/
========================================================================
至此,困扰我好几个月的显示和2D加速问题终于解决。
目前得出的结论为Android系统中2D加速引擎copybit对UI的加速作用并不明显。
Rockie Cheng