转载时请表明原文出处(http://blog.sina.com.cn/wyw1976)及作者邮箱(wyw1976@gmail.com)
双缓存是画图时一个常用的技术,它的基本原理是在其中一个缓存中作图,完成后提交显示,同时在另一块缓存中继续作图,这样两块缓存交替画图-显示,实现了两者的同步进行,提高了效率。
在DirectFB中,一个缓存实际就是一块内存。DFB支持两种缓存分配方式:
(1)用户自己分配,并在createSurface是将该内存地址传递给DFB,这种方式需要在createSurface时指定DSCAPS_PREMULTIPLIED属性
(2)DFB自动分配,大部分用户使用这种方式。
DirectFB支持双缓存或三缓存,用户编程时,只需在调用dfb->CreateSurface 时指定DSCAPS_DOUBLE或DSCAPS_TRIPLE即可。而除此以外,多缓存对于用户是透明的。
下面是一个简单实现动画的例子:一条横线自上而下的移动(假定我们让DFB自动分配缓存并设定它是双缓存的):
dfb->CreateSurface(dfb, &sdsc, &surface);
for(i=0;i<100;i++)
{
surface->DrawLine(surface, 100, 100+i, 200, 100+i);
sleep(1);
surface->Flip(surface, NULL, DSFLIP_WAITFORSYNC);
}
surface->Release(surface);
第一步CreateSurface(),创建一个Surface对象并初始化这个对象的函数指针,同时设置该surface的一些基本属性如大小,格式(pixel format)等。但是并没有为该surface创建缓存,也就是没有实质的内存分配。
第一次调用drawline时,首先会调用dfb_gfxcard_state_check检查和设置各个状态,其中会调用dfb_surface_get_buffer得到目标buffer,即在哪个缓存上画。它的代码如下:
dfb_surface_get_buffer( CoreSurface *surface, CoreSurfaceBufferRole role )
{
return surface->buffers[ surface->buffer_indices[(surface->flips + role) % surface->num_buffers] ];
}
关于这个函数:
role即buffer的角色,有三种CSBR_FRONT(0), CSBR_BACK(1),CSBR_IDLE(2),分别表示前缓存,后缓存和闲置缓存。
通常,总是在前缓存中画,即role总是CSBR_FRONT。另外,前缓存和后缓存只是一个逻辑概念,它所指向的buffer是交替变化的,
surface->buffers[]是一个buffer的数组,buffers[0]指向第一个buffer对象,buffers[1]指向第二个buffer对象,等等。该数组的大小是MAX_SURFACE_BUFFERS,即6个。
surface->buffer_indices[]是一个整数数组,它的大小也是6,我个人认为不需要这个变量,仍然可以工作,看不出他的真正用途是什么。
surface->num_buffers记录了这个surface有效的buffer数量,如果指定了DSCAPS_DOUBLE,那它就是2;如果指定了DSCAPS_TRIPLE,那它就是3.
surface->flips是一个整数值,系统每次调用Flip函数,这个值就会加1。
这样,我们就很容易理解上面的那个函数。例如,第一次drawline时,调用dfb_surface_get_buffer(), role是FRONE, 即0, flips = 0, 则返回的就是第一个缓存;调用Flip显示之后,第二次画图时,role仍然为FRONT,因为用户总是在前buffer中作图,而flips 变成了 1,这时上面的函数返回的是第二个缓存。第三次画图时,又返回第二个buffer,依次类推。
最终得到的buffer内存地址将传递给实际的作图函数,并由它在内存中完成作图。
这就是DFB双(多)缓存的实现。
双缓存是画图时一个常用的技术,它的基本原理是在其中一个缓存中作图,完成后提交显示,同时在另一块缓存中继续作图,这样两块缓存交替画图-显示,实现了两者的同步进行,提高了效率。
在DirectFB中,一个缓存实际就是一块内存。DFB支持两种缓存分配方式:
(1)用户自己分配,并在createSurface是将该内存地址传递给DFB,这种方式需要在createSurface时指定DSCAPS_PREMULTIPLIED属性
(2)DFB自动分配,大部分用户使用这种方式。
DirectFB支持双缓存或三缓存,用户编程时,只需在调用dfb->CreateSurface 时指定DSCAPS_DOUBLE或DSCAPS_TRIPLE即可。而除此以外,多缓存对于用户是透明的。
下面是一个简单实现动画的例子:一条横线自上而下的移动(假定我们让DFB自动分配缓存并设定它是双缓存的):
dfb->CreateSurface(dfb, &sdsc, &surface);
for(i=0;i<100;i++)
{
surface->DrawLine(surface, 100, 100+i, 200, 100+i);
sleep(1);
surface->Flip(surface, NULL, DSFLIP_WAITFORSYNC);
}
surface->Release(surface);
第一步CreateSurface(),创建一个Surface对象并初始化这个对象的函数指针,同时设置该surface的一些基本属性如大小,格式(pixel format)等。但是并没有为该surface创建缓存,也就是没有实质的内存分配。
第一次调用drawline时,首先会调用dfb_gfxcard_state_check检查和设置各个状态,其中会调用dfb_surface_get_buffer得到目标buffer,即在哪个缓存上画。它的代码如下:
dfb_surface_get_buffer( CoreSurface *surface, CoreSurfaceBufferRole role )
{
return surface->buffers[ surface->buffer_indices[(surface->flips + role) % surface->num_buffers] ];
}
关于这个函数:
role即buffer的角色,有三种CSBR_FRONT(0), CSBR_BACK(1),CSBR_IDLE(2),分别表示前缓存,后缓存和闲置缓存。
通常,总是在前缓存中画,即role总是CSBR_FRONT。另外,前缓存和后缓存只是一个逻辑概念,它所指向的buffer是交替变化的,
surface->buffers[]是一个buffer的数组,buffers[0]指向第一个buffer对象,buffers[1]指向第二个buffer对象,等等。该数组的大小是MAX_SURFACE_BUFFERS,即6个。
surface->buffer_indices[]是一个整数数组,它的大小也是6,我个人认为不需要这个变量,仍然可以工作,看不出他的真正用途是什么。
surface->num_buffers记录了这个surface有效的buffer数量,如果指定了DSCAPS_DOUBLE,那它就是2;如果指定了DSCAPS_TRIPLE,那它就是3.
surface->flips是一个整数值,系统每次调用Flip函数,这个值就会加1。
这样,我们就很容易理解上面的那个函数。例如,第一次drawline时,调用dfb_surface_get_buffer(), role是FRONE, 即0, flips = 0, 则返回的就是第一个缓存;调用Flip显示之后,第二次画图时,role仍然为FRONT,因为用户总是在前buffer中作图,而flips 变成了 1,这时上面的函数返回的是第二个缓存。第三次画图时,又返回第二个buffer,依次类推。
最终得到的buffer内存地址将传递给实际的作图函数,并由它在内存中完成作图。
这就是DFB双(多)缓存的实现。