2015-12-14 53 views
1

有沒有辦法從其他線程使用glwidget的qglcontext。因爲我需要從其他線程做一些紋理上傳。但是在紋理上傳之後,甚至在它上下文中,也必須在我的渲染glwidget的服務中。是否有文檔或堅實(假設免費)的答案?使用其他線程的qglcontext

+0

我的回答有幫助嗎? – Mykola

+0

@Mykola請注意,由於沒有提供任何反饋,OP可能會在某些答案上出現奇怪的行爲。請參閱[this](http://meta.stackoverflow.com/questions/317470/what-c​​an-i-do-if-a-user-removes-a-question-after-ive-written-an-extended-answer )meta例如。 – eAbi

+0

@eAbi:我對此已經有了不好的一面。 – Mykola

回答

1

OpenGL不支持多線程渲染,所有OpenGL調用必須從創建上下文的線程執行。但是如果你不想加載紋理,你可以從其他線程加載它,而不是將結果發佈到該線程,例如,將該OpenGL上下文創建爲glTexImage2D,作爲圖像信息。要做到這一點,必須添加一些線程管理(信號e.t.c ...)。

欲瞭解更多信息,請看Concurrency and OpenGL

QGLWidget multithreaded example?

要從其他線程工作,您必須與他們創建單獨的上下文或執行一些共享上下文管理。


來自官方的Qt文檔:

隨着版本的Qt 4.8,做線程渲染GL的支持得到了提高。我們目前支持三種場景:

  1. 緩衝區交換在一個線程中。 在雙緩衝上下文中交換緩衝區可能是一個同步的鎖定調用,在某些GL實現中可能是一個代價高昂的操作。特別是嵌入式設備。當GPU正在進行緩衝區交換時,讓CPU空閒是不理想的。在這些情況下,可以在主線程中執行渲染,並在單獨的線程中進行實際的緩衝區交換。這可以通過以下步驟完成:

    1. 當渲染完成時,在主線程中調用doneCurrent()

    2. 調用QGLContext::moveToThread(swapThread)將上下文的所有權轉移給交換線程。

    3. 通知它可以獲取上下文的交換線程。

    4. 在交換線程中使當前渲染上下文與makeCurrent()一致,然後調用swapBuffers()

    5. 在交換線程中調用doneCurrent()

    6. 調用QGLContext::moveToThread(qApp->thread())並通知主線程已完成交換。

這樣做會釋放主線程,以便它可以繼續,例如,處理UI事件或網絡請求。即使涉及上下文交換,與GPU完成交換操作時主線程等待相比,它可能更好。請注意,這非常依賴於實施。

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

  2. 使用QPainte r在線程中繪製成QGLWidget。 在Qt 4.8中,可以在單獨的線程中使用QPainter來繪製QGLWidget。請注意,對於QGLPixelBuffersQGLFramebufferObjects,這也是可能的。由於這僅在GL 2繪圖引擎中受到支持,因此需要OpenGL 2.0或OpenGL ES 2.0。

QGLWidgets只能在主GUI線程中創建。這意味着需要調用doneCurrent()才能在主線程釋放GL上下文,然後才能通過另一個線程來引用該小部件。然後您需要致電QGLContext::moveToThread()將上下文的所有權轉移到您希望使其最新的線程。此外,主GUI線程將在調整窗口小部件大小時調度調整大小並將事件繪製到QGLWidget,或者部分窗口暴露或需要重繪。因此,有必要處理這些事件,因爲QGLWidget中的默認實現將嘗試使QGLWidget的上下文保持最新,這將再次干擾呈現到窗口小部件中的任何線程。重新實現QGLWidget::paintEvent()QGLWidget::resizeEvent()以通知呈現線程需要調整大小或更新,並小心不要調用基類實現。如果您正在渲染動畫,則可能不需要處理繪製事件,因爲渲染線程正在進行定期更新。然後重新執行QGLWidget::paintEvent()就無能爲力了。

作爲進行線程渲染的一般規則:請注意,綁定和釋放不同線程中的上下文必須由用戶同步。 GL渲染上下文只能在任何時候在一個線程中最新。如果您嘗試在QGLWidget上打開QPainter,並且該窗口小部件的渲染上下文在另一個線程中是最新的,則該窗口將失敗。

除此之外,還支持在獨立線程中使用原始GL調用進行渲染。