雙緩衝是畫圖時一個常用的技術,它的基本原理是在其中一個緩衝中作圖,完成後提交顯示,同時在另一塊緩衝中繼續作圖,這樣兩塊緩衝交替畫圖-顯示,實現了兩者的同步進行,提高了效率。
在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雙(多)緩衝的實現。