<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    談?wù)?eglMakeCurrent、eglSwapBuffers、glFlush 和 glFinish 的區(qū)別

    共 4649字,需瀏覽 10分鐘

     ·

    2024-04-12 03:16

    最近有讀者面試被問到了這些高頻知識點(diǎn),再帶大家復(fù)習(xí)一下。


    3d3bf4017d1f8df6c74ddc63d0205ebe.webp

    eglMakeCurrent

    記得這個調(diào)用嗎?方法原型是:

          
            EGLBoolean eglMakeCurrent(
    EGLDisplay display,
    EGLSurface draw,
    EGLSurface read,
    EGLContext context
    )
    ;

    為了弄懂這個方法,我們需要搞清楚 Display 、 Surface 、 Context 這幾個概念。

    Display

    在使用EGL 的過程中,會發(fā)現(xiàn)EGL 相關(guān)的調(diào)用都經(jīng)常需要我們傳入一個類型為 Display 的參數(shù)。

    顧名思義, Display 是一個連接,用于連接設(shè)備上的底層窗口系統(tǒng)。

    所以在調(diào)用EGL 方法之前,需要先創(chuàng)建、初始化這個 Display 連接。步驟如下:

          
            EGLint majorVersion;
    EGLint minorVersion;
    EGLDisplay display;
    display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (display == EGL_NO_DISPLAY) {
    // 無法打開到底層窗口系統(tǒng)的連接
    }
    if (!eglInitialize(display, &majorVersion, &minorVersion)) {
    // 無法初始化EGL
    }

    通常情況下傳入 EGL_DEFAULT_DISPLAY 作為 eglGetDisplay 的參數(shù)就可以了,EGL 會自動返回默認(rèn)的 Display

    Context

    Context 不是什么神秘的東西,它僅僅是一個容器,里面放著兩個東西:

    • 內(nèi)部狀態(tài)信息 (View port, depth range, clear color, textures, VBO, FBO, ...)

    • 調(diào)用緩存 ,保存了在這個 Context 下發(fā)起的GL調(diào)用指令。(OpenGL 調(diào)用是異步的)

    總的來說, Context 是設(shè)計來存儲渲染相關(guān)的輸入數(shù)據(jù)。

    Surface

    對應(yīng)的 Surface 則是設(shè)計來存儲渲染相關(guān)的輸出數(shù)據(jù)。

    Surface 實(shí)際上是一個對底層窗口對象的拓展、或是一個有著額外輔助緩沖的像素映射(pixmap)。這些輔助緩存包括顏色緩存(color buffer)、深度緩沖(depth buffer)、模板緩沖(stencil buffer)。

    再回到 eglMakeCurrent

    那么eglMakeCurrent到底做了什么?

    當(dāng)發(fā)起 GL 調(diào)用指令(如:glDrawElements)的時候,這個調(diào)用會影響到哪個Context和Surface呢?答案就在 eglMakeCurrent 。

          EGLBoolean eglMakeCurrent(
    EGLDisplay display,
    EGLSurface draw,
    EGLSurface read,
    EGLContext context
    )
    ;

    eglMakeCurrent context 綁定到當(dāng)前的渲染線程以及 draw read 指定的Surface。

    draw 用于除數(shù)據(jù)回讀(glReadPixels、glCopyTexImage2D和glCopyTexSubImage2D)之外的所有GL 操作。

    回讀操作作用于read指定的Surface上的幀緩沖(frame buffer)。

    因此,當(dāng)我們在線程T上調(diào)用GL 指令,OpenGL ES 會查詢T線程綁定是哪個Context C,進(jìn)而查詢是哪個Surface draw和哪個Surface read綁定到了這個Context C上。

    多個Context

    某些情況下,我們想創(chuàng)建、使用多個Context,對于這種情況,需要注意以下幾個情況:

    • 不能在2個線程里綁定同一個 Context 。

    • 不能在2個不同的線程里,綁定相同的 Surface 到2個不同的 Context 。

    • 在2個不同的線程里,綁定2個不同 Surface 到2個 Context 上,取決于使用的GPU的具體實(shí)現(xiàn),可能成功,也可能失敗

    共享Context

    共享Context這種方式在加載階段很有用。由于上傳數(shù)據(jù)到GPU(尤其是紋理數(shù)據(jù)(textures))這類操作很重,如果想要維持幀率穩(wěn)定,應(yīng)該在另一個線程進(jìn)行上傳

    然而,出于上述3種情況的限制,必須在第一個Context之外,創(chuàng)建第二個Context,這個Context將使用第一個Context使用的內(nèi)部狀態(tài)信息。這兩個Context即共享Context。

    需要注意的是:這兩個Context共享的只是內(nèi)部狀態(tài)信息,它們兩個并不共享調(diào)用緩存(每個Context各自擁有一個調(diào)用緩存)。

    創(chuàng)建第二個Context的方法:

          EGLContext eglCreateContext(
    EGLDisplay display,
    EGLConfig config,
    EGLContext share_context,
    EGLint const * attrib_list)
    ;

    第三個參數(shù) share_context 是最重要的,它就是第一個Context。

    在第二個線程,不進(jìn)行任何的繪制,只進(jìn)行上傳數(shù)據(jù)到GPU 的操作。所以,給第二個Context 的Surface 應(yīng)該是一個像素緩沖(pixel buffer)Surface。

          EGLSurface eglCreatePbufferSurface(
    EGLDisplay display,
    EGLConfig config,
    EGLint const * attrib_list)
    ;

    eglSwapBuffers

          EGLBoolean eglSwapBuffers(
    EGLDisplay display,
    EGLSurface surface)
    ;

    第一次看到這個調(diào)用的時候,我以為它的作用是對 display surface 進(jìn)行交換:) 槑

    實(shí)際上,這里需要重點(diǎn)注意的是 surface 。如果這里的`surface
    是一個像素緩沖(pixel buffer)Surface,那什么都不會發(fā)生,調(diào)用將正確的返回,不報任何錯誤。

    但如果 surface 是一個雙重緩沖surface(大多數(shù)情況),這個方法將會交換 surface 內(nèi)部的前端緩沖(front-buffer)和后端緩沖(back-surface)。

    后端緩沖用于存儲渲染結(jié)果,前端緩沖則用于底層窗口系統(tǒng),底層窗口系統(tǒng)將緩沖中的顏色信息顯示到設(shè)備上。

    glFlush 和 glFinish

    OpenGL ES 驅(qū)動和GPU以并行/異步的機(jī)制運(yùn)行。發(fā)起GL 調(diào)用時,為了得到最好的性能,驅(qū)動會嘗試盡快地把調(diào)用指令發(fā)送給GPU。

    但GPU 并不會馬上執(zhí)行這些指令,這些指令只是添加到了GPU的指令隊列里等待GPU 執(zhí)行。

    如果在短時間內(nèi)發(fā)送大量的GL 指令給GPU,GPU的指令隊列可能滿了,以至于驅(qū)動需要把這些指令保存在Context的調(diào)用緩存里(即上文里提到的Context內(nèi)的調(diào)用緩存)。

    那么問題來了,這些等待中的指令何時會發(fā)送給GPU呢?

    通常來說,大多數(shù) OpenGL ES 驅(qū)動的實(shí)現(xiàn)可能會在發(fā)起新的(下一個)GL 指令發(fā)起的時候發(fā)送這些指令。如果想要主動執(zhí)行這個操作,那就調(diào)用 glFlush

    這個操作將會阻塞當(dāng)前線程,直到所有的指令都發(fā)送給了 GPU 。 glFinish 這個命令更加強(qiáng)大,它會阻塞當(dāng)前線程,直到所有的指令都發(fā)送給了GPU,并執(zhí)行完畢。需要注意的是,應(yīng)用程序的性能會因此下降。

    glFlush glFinish 被稱為顯式同步操作。某些情況下也會發(fā)生隱式同步操作。調(diào)用 eglSwapBuffers 時,就可能發(fā)生這種情況。

    由于這個操作是由驅(qū)動直接執(zhí)行的,此時GPU 可能把所有待執(zhí)行的 glDraw* 繪制指令,作用在一個不符合預(yù)期的surface 緩沖上(如果之前前端緩沖和后端緩沖已經(jīng)交換過了)。

    為了防止這種情形,在交換緩沖前,驅(qū)動必須阻塞當(dāng)前線程,等待所有的影響當(dāng)前surface的 glDraw* 指令執(zhí)行完畢。

    當(dāng)然,使用雙重緩沖的surfaces時,不需要主動調(diào)用 glFlush glFinish :因?yàn)?/span> eglSwapBuffers 進(jìn)行了隱式同步操作。

    但在使用單緩沖surfaces(如上文提到的第二個線程里)的情況,需要及時調(diào)用 glFlush ,例如:在線程退出前,必須調(diào)用 glFlush ,否則,GL 指令可能從未發(fā)送到GPU。

    End

    原文鏈接: Let’s talk about eglMakeCurrent, eglSwapBuffers, glFlush, glFinish

    https://katatunix.wordpress.com/2014/09/17/lets-talk-about-eglmakecurrent-eglswapbuffers-glflush-glfinish/


    -- END --


    進(jìn)技術(shù)交流群,掃碼添加我的微信:Byte-Flow



    獲取相關(guān)資料和源碼


    學(xué)習(xí)音視頻、OpenGL ES、Vulkan 、Metal、圖像濾鏡、視頻特效及相關(guān)渲染技術(shù)的付費(fèi)社群,面試指導(dǎo),1v1 簡歷服務(wù),職業(yè)規(guī)劃。


    我的付費(fèi)社群


    推薦:

    Android FFmpeg 實(shí)現(xiàn)帶濾鏡的微信小視頻錄制功能

    全網(wǎng)最全的 Android 音視頻和 OpenGL ES 干貨,都在這了

    一文掌握 YUV 圖像的基本處理

    抖音傳送帶特效是怎么實(shí)現(xiàn)的?

    所有你想要的圖片轉(zhuǎn)場效果,都在這了

    面試官:如何利用 Shader 實(shí)現(xiàn) RGBA 到 NV21 圖像格式轉(zhuǎn)換?

    我用 OpenGL ES 給小姐姐做了幾個抖音濾鏡

    瀏覽 27
    點(diǎn)贊
    評論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報
    評論
    圖片
    表情
    推薦
    點(diǎn)贊
    評論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    在线操b| 国产操比视频 | 成人无码AV高潮大毛片 | 亚洲欧洲日韩综合 | 粉嫩护士小泬18p |