2012-09-25 47 views
0

我正在嘗試使用QGLWidget實現CoverFlow效果,問題在於紋理加載過程。Qt4/Opengl bindTexture在分離線程中

我有一個工作(QThread)從磁盤加載圖像,主線程檢查新加載的圖像,如果它發現任何然後使用bindTexture將它們加載到QGLContext中。當紋理被綁定時,主線程被阻塞,所以我有一個fps的下降。

這樣做的正確方法是什麼?

回答

0

在主線程(單QGLWidget溶液)的結合:

  1. 決定最大紋理大小。例如,您可以根據最大可能的小部件大小來決定它。假設您知道該窗口小部件最多可以(大約)800x600像素,並且最大的可見屏幕上下可以看到30像素的邊距,並且縱橫比爲1:2 - > 600-2 * 30 = 540 - >封面的最大尺寸爲270x540,例如存儲在m_maxCoverSize

  2. 在加載程序線程中將傳入圖像縮放到該大小。綁定較大的紋理並沒有意義,並且它越大,上傳到顯卡所需的時間就越長。使用QImage::scaled(m_maxCoverSize, Qt::KeepAspectRatio)來縮放加載的圖像並將其傳遞給主線程。

  3. 限制紋理的數量或更好地花費每幀綁定它們的時間。即記住你開始綁定紋理的時間(例如QTime bindStartTime;),並綁定每個紋理之後:

    if(bindStartTime.elapsed()> BIND_TIME_LIMIT) break;

BIND_TIME_LIMIT將取決於你想保留的幀頻。但是,當然,如果綁定每一個紋理需要比BIND_TIME_LIMIT長得多的時間,你還沒有解決任何問題。

儘管在較慢的機器/圖形卡上加載圖像,但您仍然可能會遇到幀率下降。其餘的代碼應該準備好與它一起生活(例如,使用實際的時間來驅動動畫)。


替代溶液是在單獨的線程綁定(使用第二隱形QGLWidget,見):在一個線程

2.紋理上傳。

在處理大量需要顯示的圖像的應用程序中執行紋理上傳可能非常有用,例如照片庫應用程序。 Qt通過現有的bindTexture()API支持這一點。一個簡單的方法是創建兩個共享的QGLWidgets。一個是在主GUI線程中創建的,另一個是在紋理上傳線程中創建的。上傳線程中的小部件從不顯示,它僅用於與主線程共享紋理。對於通過bindTexture()綁定的每個紋理,請通知主線程,以便它可以開始使用紋理。

+0

問題是紋理大小,我使用480x700圖像(或多或少),但每個封面都有自己的大小(480x741,480x744,640x437),以保持封面的高寬比。我已經縮小了工作線程上的覆蓋範圍,但取決於顯卡,封面尺寸必須縮放太多。 – louissmr

+0

爲什麼會出現這種問題? – artm

+0

對不起,我的評論不完整。 – louissmr

2

我發現bindTexture在Qt4的默認行爲是extremelly慢:

bindTexture(image,target,format,LinearFilteringBindOption | InvertedYBindOption | MipmapBindOption) 

僅使用綁定選項LinearFilteringBindOption加快了很多東西,這是我當前的呼叫:

bindTexture(image, GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption); 

的詳細信息here:加載時間爲3800x2850 bmp文件2秒降低到34毫秒

當然,如果你需要mipmapping,這不是解決方案。在這種情況下,我認爲要走的路是像素緩衝區對象。

+0

因此,生成兩個大小的紋理的非大功率的mipmap很慢,爲什麼您認爲Pixel Buffers會有所作爲? – artm

+0

PBO可以使用DMA將像素數據傳輸到圖形卡,而不涉及CPU週期,不是嗎?因此,在分離線程中使用PBO可以解決問題。 – louissmr

+0

任何圖形驅動程序都可以優化上傳PBO,以優化上傳紋理。對這種尺寸的圖片進行mipmap處理的問題不僅僅是轉移,而是它將擴展到4096x4096並縮小12倍以形成mipmap。這些操作不會通過切換到PBO加快,事實上我不明白PBO如何與mipmapping完全相關。 – artm