2016-03-21 90 views

回答

1

您不能從另一個線程執行glReadPixels(),因爲EGL上下文一次只能在一個線程中處於當前狀態,並且您無法使用GLSurfaceView控制它。

然而,花了抓住從GLES屏幕截圖的時間95 +%用於PNG/JPEG壓縮和磁盤I/O。因此,如果您從onDrawFrame()撥打電話glReadPixels(),然後將數據交給一個新線程,那麼在屏幕快照在後臺處理時應該可以繼續運行。

1

如前所述的直接讀取可從另一個線程是不可能的,但也有其他方式。

代替直接繪製場景的表面的視圖可能它繪製到幀緩衝器的對象(FBO)附有紋理,然後重新繪製紋理到主緩衝區。這是用於後期處理的非常標準的過程,並且不具有高性能影響。爲了實現這一點,您實際上只需要研究如何創建FBO,在繪圖開始之前將其綁定,並且其餘代碼應該保持原樣。然後,通過綁定主緩衝區(索引0應該這樣做),添加代碼來重畫屏幕上的FBO紋理。

對於一個單獨的線程,你現在需要創建一個新的線程,並且是在該線程設置一個新的上下文的屏幕截圖。新的背景必須與主背景共享(我相信有一個構造函數接受主背景),所以你可以共享紋理。現在有趣的部分:當您想要截取屏幕截圖時,您需要創建一個新紋理,將新紋理附加到FBO,分離舊紋理。通過這樣做,您可以竊取內容被繪製的紋理,並且您可以隨心所欲地執行任何您想要的任何線程。因此,把它放到你的輔助線程中,在這個上下文中你可以創建另一個FBO,將它綁定並在該線程上讀取它的像素。不要忘記清理。

有些謹慎,雖然建議。當您製作相對較少量的屏幕截圖時,這種過程可能會很好。如果一個截圖在另一個截圖開始之前沒有完全完成,那麼您的內存使用量將會膨脹,並且您的應用很可能會崩潰。所以要小心不要這樣做,創建某種鎖定機制或限制正在進行的截圖處理的數量。這不僅適用於openGL,簡單編碼圖像數據時可能會出現同樣的問題。

而就在你最初的想法記:即使你可以使用一個單獨的線程的表面視圖和讀取它的主緩衝區像素您可能沒有想到你會得到一個好的結果。讀取時緩衝區可能會被吸引,因此您可能會從不同的幀獲得大量數據。這仍然是理論上的,因爲事實是緩衝區會被鎖定,並且您的應用程序在嘗試訪問時會崩潰。所以這是不可能的,即使它的結果是不可預測的。

+0

小心 - 在不同線程的上下文之間共享紋理可能存在競爭條件。我在Grafika得到了這個錯誤;請參閱https://github.com/google/grafika/issues/36。 – fadden

+0

這就是爲什麼我說你需要「偷走」紋理。您需要將您繪製的當前紋理替換爲新紋理。你實際上可以使用2個紋理進行雙緩衝。 –

相關問題